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.
with() function is used to eager load in Laravel. Unless of using 2 or more separate queries to fetch data from the database , we can use it with() method after the first command. It provides a better user experience as we do not have to wait for a longer period of time in fetching data from the database.
A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With