【问题标题】:Laravel Eloquent: n+1 accessing related model via accessorLaravel Eloquent:n+1 通过访问器访问相关模型
【发布时间】:2014-04-02 12:47:30
【问题描述】:

我在 Laravel 中抽象模型依赖时遇到问题。

我有一个Metal 模型和一个Fix 模型。一个 Metal 有很多 Fixes,但是当我查询 Metal 模型时,我需要 Metal 模型上的一个属性,该属性依赖于特定的关联修复。

我使用访问器来执行此操作,该访问器从金属模型中查询修复模型。

下面的例子:

class Metal extends Eloquent
{
  protected $table = 'metals';

  public function fixes()
  {
    return $this->hasMany('Fix');
  }

  public function getFixAttribute()
  {
    $fix = Fix::where('metal_id', $this->id)
    ->where('currency_id', Session::get('currency'))->remember(10)->first();

    $amFix = $fix->am;

    return $amFix;
  }

  protected $appends = array('fix');
}

如果没有->remember(10),每次需要金属模型时,我最终都会对金属表中查询的每一行执行一次数据库查询。 n+1 问题。

示例 - 假设数据库中有 10 种金属,dd(Metal::all()); 将查询金属表,然后对修复表进行 10 次查询以获取每种金属的修复属性。

此外,我不需要每次都使用 fixAttribute,但我会经常需要它——这就是我附加属性访问器的原因。

解决这个问题的最佳方法是什么?谁能指出我正确的方向?

理想情况下,我想在为每种金属提供一个修复后查询修复表,然后将 metal_id 与金属表匹配并在金属修复访问器中使用它。

【问题讨论】:

    标签: php orm laravel eloquent


    【解决方案1】:

    我认为您可以使用with 方法使用Eager Loading (Eager Load Constraints) 减少n+ query problem

    $metalsWithFixes = Metal::with(array('fixes' => function($q){
        $q->where('currency_id', Session::get('currency'));
    }))->get();
    

    更新:您可以将关系用作$metalsWithFixes->first()->fixes,并且可以从fix tablw 中选择字段,但关系键(metal_id)必须存在于选择array中:

    $metalsWithFixes = Metal::with(array('fixes' => function($q){
        $q->where('currency_id', Session::get('currency'))->select(array('metal_id', 'am'));
    }))->get();
    

    您可以在view (blade) 中使用loop 作为:

    @foreach($metalsWithFixes as $metal)
    
        {{ $metal->fieldName }}
    
        @foreach($metalWithFix->fixes as $fix)
            {{ $fix->am }}
        @endforeach;
    
    @endforeach
    

    因为这是one-to-many 关系,所以$metal->fixes 将返回多个fix 或一个(如果只有一个)但作为array

    【讨论】:

    • 太好了,谢谢,但是不能在Metal 模型上将它作为访问器,这样我就可以查询$metal->fix了吗?修复表中唯一需要的属性是am,如上所述。
    猜你喜欢
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    相关资源
    最近更新 更多