My goal is to select all issues that have been marked as false-positive. The issues are connected to Status
via a ManyToMany relationship with pivot table IssuesStatus
. The current status of an issue is determined by the value of the status
column on the Status
table.
I've come up with a solution that works but seems somehow suspect. I'm looking for a way to rewrite the query using Eloquent query builder without relying on the DB::raw()
method.
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();
}
Example of desired SQL query:
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
Models:
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);
}
...
}
Tables:
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
If i understood correctly, you want to fetch the issue where the latest status is equals to something.
Add a latestStatus
function to your Issues
model:
public function latestStatus()
{
return $this->hasMany(IssueStatus::class)->latest();
}
Now, swap your status
function with this one:
public function status() {
return $this->belongsToMany( Status::class, 'issues-status')
->withTimestamps()
->withPivot('note');
}
Then:
//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;
});
Hope it helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.