Scott-David Jones
Scott-David Jones

Reputation: 412

Laravel model belongs to relationship loading issue

I have two models, Box and BoxLocations. Box has a hasMany relation to BoxLocations and BoxLocations has a belongsTo relationship to Box.

BoxLocations also has an attribute that is appended to the model that required a single piece of information from the Box relation.

I have noticed that when calling Box::with(['BoxLocations']->)all(); I see that the BoxLocations model is re-loading the Box relationship. This is happening for each BoxLocation (50 odd times)

Does laravel not track that the Box was already loaded from the initial Box::with(['BoxLocations']->)all(); request and then pass this to the BelongsTo relationship?

I am trying to optimise a web system and when the taken attribute is loaded (annoyingly its required every time its loaded as well) its causing 50 odd hits to the database for the same Box model it has already loaded.

If laravel does not do this - is there a better way in which to achieve the above?

Upvotes: 0

Views: 1601

Answers (1)

Piazzi
Piazzi

Reputation: 2636

Laravel uses eager loading when you use the with() method.

When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem.

So if you do this:

$boxes = Box::with('BoxLocations')->get();

It will load the relations already, but lets' say you do this:

$boxes = Box::all();

foreach($boxes as $box)
{
  echo box->boxlocation->name;
}

If you have 50 Boxes, this loop would run 51 queries.

But when you use the with method and eager load the relation, this loop will run only 2 queries.

You could also use Lazy Eager Loading and decide when you want to load the relationship

Upvotes: 1

Related Questions