Good day,
I'm a bit stuck here with fetching latest item using Laravel scopes and Eloquent Polymorphic One-to-Many relationship.
Given:
- I'm using latest version of Laravel 6.x.
- I have two models:
Website
andStatus
. Status
model is reusable and can be used with other models.- Each website has multiple statuses.
- Every time status is changed a new record is created in DB.
- Active website status is the latest one in the DB.
Websites model:
class Website extends Model
{
public function statuses()
{
return $this->morphMany(Statuses::class, 'stateable');
}
public function scopePending($query)
{
return $query->whereHas('statuses', function ($query) {
$query->getByStatusCode('pending');
});
}
}
Statuses model:
class Statuses extends Model
{
public function stateable()
{
return $this->morphTo();
}
public function scopeGetByStatusCode($query, $statusCode)
{
return $query->where('status_code', $statusCode)->latest()->limit(1);
}
}
The problem is that when I call:
Website::pending()->get();
The pending()
scope will return all websites that have ever got a pending
status assigned to them, and not the websites that have currently active pending
status (eg. latest status).
Here is the query that is returned with DB::getQueryLog()
select * from `websites`
where exists
(
select * from `statuses`
where `websites`.`id` = `statuses`.`stateable_id`
and `statuses`.`stateable_type` = "App\\Models\\Website"
and `status_code` = 'pending'
order by `created_at` desc limit 1
)
and `websites`.`deleted_at` is null
What is the right way of obtaining pending
websites using scope with polymorphic one-to-many relation?
Similar issue is descried here: https://laracasts.com/discuss/channels/eloquent/polymorphic-relations-and-scope
Thanks.
websites.id
instead ofwebsite.id
. – Kevin Bui