首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不使用DB::raw()的Laravel 5.8雄辩查询--根据多对多关系的最新值获取行

不使用DB::raw()的Laravel 5.8雄辩查询--根据多对多关系的最新值获取行
EN

Stack Overflow用户
提问于 2019-07-19 01:42:30
回答 1查看 495关注 0票数 0

我的目标是选择所有标记为假阳性的问题。这些问题通过与透视表IssuesStatus的ManyToMany关系连接到Status。问题的当前状态由Status表上status列的值确定。

我想出了一个有效的解决方案,但似乎有些可疑。我正在寻找一种使用Eloquent query builder重写查询的方法,而不依赖于DB::raw()方法。

代码语言:javascript
复制
public function getFalsePositivesAttribute() {
    return Issue::where(DB::raw(
        '( select `status` '.
        'from `issues-status` '.
        'left join `status` on `status`.id = `issues-status`.status_id '.
        'where `issues-status`.issue_id = `issues`.id '.
        'order by `issues-status`.id desc limit 1 )'
    ), '=', 'false-positive')->get();
}

所需SQL查询的示例:

代码语言:javascript
复制
SELECT
    `Issues`.id
FROM
    `issues` AS `Issues`
LEFT JOIN
    `issues-status` `IssueStatus` on `Issues`.id = `IssueStatus`.issue_id
LEFT JOIN
    `status` as `StatusTable` on `IssueStatus`.status_id = `StatusTable`.id
WHERE
    `Issues`.report_id = 2
AND
    ( 
        SELECT
            `status`
        FROM
            `issues-status` `IssueStatus`
        LEFT JOIN
            `status` `StatusTable` on `StatusTable`.id = `IssueStatus`.status_id
        WHERE
            `IssueStatus`.issue_id = `Issues`.id
        ORDER BY
            `IssueStatus`.id desc
        LIMIT 1
    ) = 'false-positive'
GROUP BY
    `Issues`.id

型号:

代码语言:javascript
复制
class Issue extends Model {
    ...

    public function status() {
        return $this->belongsToMany( Status::class, 'issues-status')
            ->withTimestamps()
            ->withPivot('note');
    }

    ...
} 

class Status extends Model {
    ...

    public function issues() {
        return $this->hasMany(Issue::class);
    }

    ...
}

表:

代码语言:javascript
复制
Issues:
  id - identity

Status
  id - identity
  status - string

IssueStatus
  id - identity
  issue_id - relation to Issues
  status_id - relation to Status
  created_at - timestamp
  note - text
EN

回答 1

Stack Overflow用户

发布于 2019-07-19 02:13:26

如果我理解正确的话,您希望获取最新状态等于某项的问题。

向您的Issues模型添加一个latestStatus函数:

代码语言:javascript
复制
public function latestStatus()
{
    return $this->hasMany(IssueStatus::class)->latest();
}

现在,将您的status函数替换为以下函数:

代码语言:javascript
复制
public function status() {
    return $this->belongsToMany( Status::class, 'issues-status')
       ->withTimestamps()
       ->withPivot('note');
}

然后:

代码语言:javascript
复制
//Get all issues which has the desired status
Issue::whereHas('status', function($query){
    $query->where('id', $desiredStatusId);
})
->get()
->reject(function($issue){ 
    //filter the collection by the latest issue status,
    // and reject those who does not have the desired latest status;
    return $issue->latestStatus()->first()->status_id != $desiredStatusId;
});

希望能有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57100029

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档