Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Laravel whenLoaded() deeper than one level

Tags:

php

laravel

How do I use whenLoaded() for deeper than one level relations? It seems as if one can only use whenLoaded with the first relation depth like this:

'season' => $this->whenLoaded('origin', function () {
    return new SeasonResource($this->origin->season);
}),

But then Laravel, if origin is loaded, but not season, Laravel will load it, which creates an N+1 problem. Both origin and season relationships are conditional, and not always used. Therefor I want to use something like this:

$this->whenLoaded('origin.season', ...)

or this:

'season' => $this->whenLoaded('origin', function () {
     return new SeasonResource($this->origin->whenLoaded('season'));
}),

Neither of these work. I suppose the deeper relations are not stored on the model itself, and in the second case, whenLoaded() does not exists on the query builder.

How do I use whenLoaded() for deeper than one level relations?

like image 685
Fredrik Avatar asked Apr 22 '18 10:04

Fredrik


1 Answers

I believe the reason this is not implemented is because it only makes sense for hasOne and belongsTo relationships (relationships that return an object, not a collection).

But if that is the case for you, you could do this:

'season' => $this->when(
    $this->relationLoaded('origin') &&
    $this->origin->relationLoaded('season'),
    function () {
        return new SeasonResource($this->origin->season);
    }
),

Basically, use ->when instead of ->whenLoaded and manually check if the relation is loaded using the ->relationLoaded public method on the model.

like image 100
DevK Avatar answered Nov 07 '22 10:11

DevK