Skip to content
Advertisement

Using Laravel whenLoaded() deeper than one level

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?

Advertisement

Answer

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.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement