问题
class Parent extends Model
{
public function kids()
{
return $this->belongsToMany('App\Models\Kid')
->orderBy('age')
->withTimestamps();
}
public function oldestKid()
{
return $this->belongsToMany('App\Models\Kid')
->orderByDesc('age')
->take(1);
}
}
Problem with this approach is that $parent->oldestKid
returns an array. It would feel more logical if it would return an object.
$parent = App\Models\Parent::with('oldestKid')->first();
回答1:
This is what we ended up with, and its working.
Important to add: the pivot table is kid_parent
public function oldestKid()
{
return $this->belongsTo(Kid::class, 'oldest_kid_id', 'id');
}
public function scopeWithOldestKid($query)
{
$query->addSelect(['oldest_kid_id' => KidParent::select('kid_id')
->whereColumn('parent_id', 'parents.id')
->join('kids', 'kids.id', '=', 'kid_parent.kid_id')
->orderByDesc('kids.age')
->take(1)
])->with('oldestKid');
}
then you can use it like that :
$parents = Parent::withOldestKid()->get();
foreach($parents as $parent){
$oldest_kid = $parent->oldestKid;
}
If you want to go crazy: you can use https://laravel.com/docs/8.x/eloquent#global-scopes so it is always loaded in if you go for a parent.
回答2:
You have to use a subquery to do that :
public function oldestKid()
{
return $this->belongsTo(Kid::class);
}
public function scopeWithOldestKid($query)
{
$query->addSelect(['oldest_kid_id' => Kid::select('id')
->whereColumn('parent_id', 'parents.id')
-> orderByDesc('age')
->take(1)
])->with('oldestKid');
}
then you can use it like that :
$parents = Parent::withOldestKid()->get();
foreach($parents as $parent){
$oldest_kid = $parent->oldestKid;
}
来源:https://stackoverflow.com/questions/64440891/how-to-return-one-instance-of-a-eloquent-many-to-many-relation-with-eager-loadin