There are 4 tables:
bundles
: id, name products
: id, nameprices
: id, namebundle_product
: id, bundle_id, product_id, price_idThere are 3 models:
Bundle
Product
Price
A Product
has a Price
when in a Bundle
. I want to have all bundles
with their associated products
and associated prices
. I can get all bundles with their product and the price id:
// I created a Bundle Model with a products method
class Bundle extends Model
{
public function products()
{
return $this->belongsToMany(Product::class)->withPivot('price_id');
}
}
// Then I call this in a controller
$all_bundles = Bundle::with('products')->get();
// Then I can get the price Id of the first product of the first bundle
$price_id = Bundle::with('products')->first()
->products()->first()
->pivot->price_id;
But I dont want the price id, I want the price Model. Is there any way to preload the price from the pivot (with Eager Loading)?
At its core Eager Loading, is telling Eloquent that you want to grab a model with specific relationships that way the framework produces a more performant query to grab all the data you will need. By eager loading, you can take many queries down to just one or two.
The main difference between eager and lazy loading is eager loading get all data with relationship records in single query and lazy loading require N+1 queries for getting main model and relation data. Eager loading run single query whereas lazy loading run N+1 queries.
Eager loading is a concept in which when retrieving items, you get all the needed items together with all (or most) related items at the same time. This is in contrast to lazy loading where you only get one item at one go and then retrieve related items only when needed.
On the relationships for both User and Target , tack on a ->withPivot('type') which will instruct Laravel to include that column. Then once you have your result set, you can access the field with $user->pivot->type .
The current accepted answer deviates from the original data structure. I created a package which can help you achieve what you want and also it maintains the original data structure. Please read my medium story here: https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a
First, create your custom pivot model and define relations on pivot model, in your case:
use Illuminate\Database\Eloquent\Relations\Pivot;
class BundleProduct extends Pivot
{
public function price()
{
return $this->belongsTo(Price::class);
}
}
Then use the pivot model in the relation:
class Bundle extends Model
{
public function products()
{
return $this->belongsToMany(Product::class)
->withPivot('price_id') // this is needed to query the relation `price`
->using(BundleProduct::class);
}
}
Make sure you use the trait AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait
in the Product
model because it is the related model in belongsToMany relation. This let us enable eager loading the pivot relations.
use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;
class Product extends Model
{
use EagerLoadPivotTrait;
}
Then eager load it like this:
$bundle = Bundle::with('products.pivot.price')->first();
$price = $bundle->products->first()->pivot->price;
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