Laravel hasManyThrough
hasManyThrough
is not the way at all. It works only for relations like this:
A hasMany/hasOne B, B hasMany/hasOne C, then A hasManyThrough C (through B)
What you have here is a many to many (belongsToMany
), with meta
being the pivot table.
So you can do this (assuming meta
is table name, Booking and MetaType are models):
// Booking model
public function meta()
{
return $this->belongsToMany('MetaType', 'meta', 'booking_id', 'metatype_id')
->withPivot([ ARRAY OF FIELDS YOU NEED FROM meta TABLE ]);
}
Then you can access all associated MetaType:
$booking->meta; // collection of MetaType models
query it like this (eager loading):
$booking = Booking::with(['meta' => function ($q) {
// query related table
$q->where('someFieldOnMetaTypeTable', 'someValue')
// and / or pivot table
->wherePivot('someFieldOnMetaTable', 'anotherValue');
}])->first();
or set constraints on the related table to filter the Booking:
$booking = Booking::whereHas('meta', function ($q) {
// query related table
$q->where('someFieldOnMetaTypeTable', 'someValue')
// and / or pivot table
->where('meta.someFieldOnMetaTable', 'anotherValue');
})->first();
Note: wherePivot
works only when you eager load the relationship, so you can't use it in whereHas
closure.
Related videos on Youtube
Greg
Updated on November 18, 2020Comments
-
Greg over 3 years
I'm struggling to get my head around a hasManyThrough concept with laravel. I have three tables:
Bookings -id (int) -some other fields Meta -id (int) -booking_id (int) -metatype_id (int) -some other fields MetaType -id (int) -name (string) -some other fields
What I am trying to get is an Eloquent model that allows me to have a single booking record with multiple Meta records of type MetaType. I thought that hasManyThrough might have solved this, but now I am thinking that perhaps this is not the best way.
In my booking model I have
public function bookingmeta() { return $this->hasMany('bookingmeta','booking_id'); } public function bookingmetatype() { return $this->hasManyThrough('bookingmetatype','bookingmeta','booking_id','bookingmetatype_id'); }
But this fails to generate the correct SQL and fails. I get
select `new_bookingmetatype`.*, `new_bookingmeta`.`booking_id` from `new_bookingmetatype` inner join `new_bookingmeta` on `new_bookingmeta`.`bookingmetatype_id` = `new_bookingmetatype`.`id` where `new_bookingmeta`.`booking_id` in (57103)
Whereas what I am really trying to achieve is
select `new_bookingmetatype`.*, `new_bookingmeta`.`booking_id` from `new_bookingmetatype` inner join `new_bookingmeta` on `new_bookingmeta`.`id` = `new_bookingmetatype`.`bookingmetatype_id` where `new_bookingmeta`.`booking_id` in (57103)
If anyone can point me in the right direction I'd really appreciate it. Thanks.
-
Milan Maharjan almost 9 yearsThanks, this makes sense :)