#Error when eager loading polymorphic relations

1 messages · Page 1 of 1 (latest)

chilly tartan
#

Hello,

First of all, to prevent N+1 queries in my app, I add this in the AppServiceProvider : Model::preventLazyLoading(app()->isLocal()); and removing it does not feel like the good solutions 😄

Here are the key models that creates my issue :

class User extends Model {}
class Team extends Model {}
class Tournament extends Model
{
    // DB column : public bool $team_based

    public function matchups(): HasMany {
        return $this->hasMany(Matchup::class);
    }

}
class Matchup extends Model
{
    public function tournament(): BelongTo {
        return $this->belongsTo(Tournament::class);
    }

    public function contestants(): MorphToMany {
        return $this->morphedByMany($this->tournament->team_based ? Team::class : User::class, 'contestant');
    }
}

The issue arises when I want to do $matchup->load('contestants') to render a match for exemple.

I run into the error : Attempt to read property "team_based" on null
Upon debugging, I found out that when dumping $this in the contestants method of my Matchup class has no attribute hydrated so the tournament attribute is null hence the error.

I have obviously check my data, and for this particular matchup, the tournament is definitely set in the database so the issue does not comes from here.
I have read the many to many polymorphic relations documentation and in the exemple, 2 methods are used (I would have to do something like teams() and users() methods but it feels annoying because in my case, it's either one or the other.

Would appreciate any help,
Thanks !

sly vessel
#

Yeah you cannot access model attributes in relation methods as it is potentially used for building a query outside of model scope.

chilly tartan
#

Damn yeah I figured I was doing something stupid 😅

#

Thanks for the link, I'll try to create the pivot class and see how it goes

sly vessel
#

Honestly the separate methods from the docs isnt a bad option you could just load both and write some logic to handle it.

#

Especially if you already have the team_based boolean on tournament.

#

Also your calling load on an individual Matchup model is that really solving N+1? Shouldn't it be eager loaded with the query to get all matchups?

chilly tartan
#

Also your calling load on an individual Matchup model is that really solving N+1? Shouldn't it be eager loaded with the query to get all matchups?
Yes well, I've purposely simplified the models/code for the post, but the load call is actually something like $tournament->load('playoff.rounds.matches.contestants') but since the issue only arose on the last part I cut out the rest 😄

Honestly the separate methods from the docs isnt a bad option you could just load both and write some logic to handle it.
I guess it could be doable, but I would have multiple place in my code where I'd have to do something like $tournament->team_based ? $tournament->load('some.relation.matches.teams' : $tournament->load('some.relation.matches.users').
And I'd like to avoid if's as much as I can