我在Laravel中抽象模型依赖项时遇到了问题。
我有Metal
模型和Fix
模型。 A Metal有很多修复,但是当我查询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)
,每次需要Metal模型时,我最终都会对金属表中查询的每一行执行db查询。 n+1
问题。
示例 - 假设数据库中有10个金属,dd(Metal::all());
将查询金属表,然后修复表10次以获取每个金属的修复属性。
此外,我不是每次都需要fixAttribute,但我会经常需要它 - 这就是我附加属性访问器的原因。
解决此问题的最佳方法是什么?任何人都可以指出我正确的方向吗?
理想情况下,我想查询修复表一次为每个金属提供一个修复,然后将metal_id与金属表匹配,并在金属修复访问器中使用它。
答案 0 :(得分:1)
我认为您可以使用Eager Loading(Eager Load Constraints
)来使用n+ query problem
方法缩小with
:
$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();
您可以在loop
中使用view (blade)
作为:
@foreach($metalsWithFixes as $metal)
{{ $metal->fieldName }}
@foreach($metalWithFix->fixes as $fix)
{{ $fix->am }}
@endforeach;
@endforeach
由于它是one-to-many
关系,因此$metal->fixes
将返回多个fix
或一个(如果只有一个)但是array