Ad

How To Use Eager Loading For Related Models In Laravel

- 1 answer

I have the following models:

  • Appointment [ belongsTo Timeslot | belongsTo User ]
  • Timeslot [ hasMany Appointment ]
  • User [ hasOne Appointment | HasOne Details ]
  • Details [ belongsTo User ]

I am trying to eager load the Details data starting from the Appointment model ( Appointment has a user, which has a Details record) using the following query:

$apps = Appointment::with('timeslot')->with('user')->with('user.details')->get();

This throws the following error in Builder.php

Call to a member function addEagerConstraints() on a non-object

Why am I calling on a non-object here and why is my query not working?

EDIT:

This is the relation on my User model:

public function details() {
    dd($this->role_id);
    switch($this->role_id) {
        case 3:
            return $this->hasOne('App\CandidateDetails', 'user_id');
            break;
        case 2:
            return $this->hasOne('App\EmployerDetails', 'user_id');
            break;
    }

}

i'm aware that this would be better implemented using a pivot table, it's been a learning process. the dd() returns a null when called by my query, yet it works fine in other calls. What's going on here?

Ad

Answer

Make sure you have return in all your relation methods. It seems that one of them is not returning a Relation definition.

You can't use $this in relation definitions - attributes of the model will be uninitiated when query is built, so $this->role_id will give null and no relation will be returned.

In order to make it work you should define 2 separate relations:

// User.php
public function candidateDetails() {
  return $this->hasOne('App\CandidateDetails', 'user_id');
}

public function cemployerDetails() {
  return $this->hasOne('App\EmployerDetails', 'user_id');
}

public function getDetailsAttribute() {
  switch($this->role_id) {
    case 3:
      return $this->candidateDetails;
    case 2:
      return $this->employerDetails;
  }
}

// ...and then...
$user = User::with('candidateDetails', 'employerDetails')->findOrFail($userId);
// depending on user's role you'll get either candidate or employer details here
$details = $user->details;
Ad
source: stackoverflow.com
Ad