2014-03-01 57 views
2

我在Laravel中抽象模型依赖关系时遇到问题。Laravel Eloquent:n + 1通过访问器访问相关模型

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

我使用访问器来查询金属模型中的修复模型。下面

实施例:

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与金属表,并使用金属修复访问者。

回答

0

我认为你可以使用Eager LoadingEager Load Constraints),以减少使用n+ query problemwith方法:

$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

+0

这很好,谢谢,但是不可能在'Metal'模型上创建一个访问器,这样我就可以查询'$ metal-> fix'了吗?修复表中唯一需要的属性就是上面的'am'。 – Gravy