Mark
Mark

Reputation: 3197

eager loading deeply nested relationships?

I have a series of tables related like so;

trainers -> hasMany -> programs
programs -> hasMany -> weeks
weeks -> hasMany -> days
days -> hasMany -> sessions
sessions -> hasMany -> phases
phases -> hasMany -> excersises

the relationships in the opposite direction are all has one accept for excersises to phases which is also hasMany with a pivot table

getting relationships one deep like this per the documentation works fine obviously

$programs = $this->program->orderBy('trainerId', 'asc')->take(1)->with('weeks.days')->get();

I need to be able to retrieve the contents of an entire program and I thought that I could eager load each nested relationship something like this

$programs = $this->program->orderBy('trainerId', 'asc')->take(1)->with('weeks.days', 'weeks.days.sessions')->get();

or

$programs = $this->program->orderBy('trainerId', 'asc')->take(1)->with('weeks.days.sessions')->get();

but both return a FatalErrorException

Call to undefined method Illuminate\Support\Facades\Session::newQuery()

whats the correct way to do this?

Upvotes: 3

Views: 3756

Answers (2)

Mark
Mark

Reputation: 3197

So I found the problem and it might help someone else to know the answer. this thread gave me the aha moment laravel forums

I have a model called Session, laravel uses that name elsewhere in the framework, duh, so when it tries to call my model it is actually calling the other session class from somewhere deep in the framework. some of the solutions i found suggest namespaces but I dont think that will work for me because the relationship declaration simply passes a string with the class name to the framework. I think this means that the calling of the class happens elsewhere and I would need to put the namespace /use there correct me if I am wrong please.

either way changing the session class to Sessionss and changing the relationships to suit has resolved my issue.

i hope this helps someone else not waste 36 hours trying to figure this out :p

Upvotes: 1

Anam
Anam

Reputation: 12169

From your question, I can see you have nested relationship like the following.

programs -> hasMany -> weeks
-----------------------------weeks -> hasMany -> days
----------------------------------------------------days -> hasMany -> sessions

It is very hard to know what data should load for days if we do not know the weeks. Similarly for the sessions as well. So, we have to load the weeks data first then days, then sessions.

From Laravel documentation, we can see, Eager loading using the following approach:

select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)

Laravel loading author data based on books data.

http://laravel.com/docs/eloquent#eager-loading

Try to load weeks first

$programs = $this->program->orderBy('trainerId', 'asc')
   ->take(1)
   ->with('weeks', 'weeks.days', 'weeks.days.sessions')
   ->get();

or:

Lazy Eager Loading:

 $programs = $this->program->orderBy('trainerId', 'asc')->take(1)->get();

 $programs->load('weeks', 'weeks.days', 'weeks.days.sessions');

Upvotes: 3

Related Questions