Question

Currently, when I'm retrieving the messages, it is presenting the n+1 issue:

select * from `messages` where `messages`.`alert_id` = '21'

This sometimes is replicated over 100+ times!

Controller function:

public function getAdminIndex() {
    $company = User::find(Auth::user()->id)
               ->companies()
               ->with('users.alerts.location')
               ->first();
    $this->layout->content = View::make('agents.admin.index', 
                             array('company' => $company));
}

User Model:

public function companies()
{
    return $this->belongsToMany('Company')->withTimestamps();
}

public function credits()
{
    return $this->hasMany('Usage');
}

public function deletedAlerts()
{
    return $this->hasMany('Alert')->onlyTrashed();
}

public function alerts()
{
    return $this->hasMany('Alert');
}

Alert Model:

public function location()
{
    return $this->belongsTo('Location');
}

public function messages()
{
    return $this->hasMany('Message');
}

Message Model:

public function alert()
{
    return $this->belongsTo('Alert');
}

public function user()
{
    return $this->belongsTo('User');
}

If I use the following line of code, I can see the MYSQL is correct, but it then can't find the location method:

->companies()
->with('users.alerts.messages.location')
->first();

select * from messages where messages.alert_id in ('21', '42')

I think it maybe a relationship issue, but I'm unsure of how to resolve it. Any help would be hugely appreciated.

Was it helpful?

Solution

The problem is that you need to load 2 relations on the Alert model (guessing without view code, but 99% sure):

public function getAdminIndex() {
$company = // User::find(Auth::user()->id)
           Auth::user()  // better approach as in @ollieread's comment
           ->companies()
           ->with('users.alerts.location', 'users.alerts.messages')
           ->first();
$this->layout->content = View::make('agents.admin.index', 
                         array('company' => $company));
}

This will execute only 1 additional query for the messages relation, because users.alerts are already loaded.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top