在雄辩的查询中停止n + 1

时间:2014-05-15 19:37:53

标签: php laravel laravel-4 eloquent

目前,当我检索messages时,它会出现n + 1问题:

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

这有时会复制超过100次!

控制器功能:

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));
}

用户模型:

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');
}

警报模型:

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

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

消息模型:

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

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

如果我使用以下代码行,我可以看到MYSQL是正确的,但它无法找到位置方法:

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

从(' 21',' 42')

中的messages.alert_id邮件中选择*

我认为这可能是一个关系问题,但我不确定如何解决它。任何帮助都将非常感激。

1 个答案:

答案 0 :(得分:1)

问题是您需要在Alert模型上加载2个关系(猜测没有查看代码,但99%肯定):

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));
}

这将只为messages关系执行一次额外查询,因为users.alerts已经加载。