2014-03-01 129 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