Tho*_*sen 9 relationships laravel eloquent laravel-4
在Laravel 4; 我有模型Project和Part,他们有一个透视表许多一对多的关系project_part.数据透视表有一列count,其中包含项目中使用的部件ID的编号,例如:
id project_id part_id count
24 6 230 3
Run Code Online (Sandbox Code Playgroud)
这里的project_id6,是使用3件part_id230.
对于同一项目,可以多次列出一个部分,例如:
id project_id part_id count
24 6 230 3
92 6 230 1
Run Code Online (Sandbox Code Playgroud)
当我显示项目的零件清单时,我不想显示part_id两次,所以我将结果分组.
我的项目模型有:
public function parts()
{
return $this->belongsToMany('Part', 'project_part', 'project_id', 'part_id')
->withPivot('count')
->withTimestamps()
->groupBy('pivot_part_id')
}
Run Code Online (Sandbox Code Playgroud)
但当然我的count价值不正确,这就是我的问题:如何获得项目所有分组部分的总和?
这意味着我的零件清单project_id应该如下所示:
part_id count
230 4
Run Code Online (Sandbox Code Playgroud)
我真的很想把它放在Projects- Parts关系中,所以我可以急于加载它.
如果没有得到N + 1问题,我无法解决如何做到这一点,任何见解都表示赞赏.
更新:作为临时解决方案,我创建了一个presenter方法来获取项目中的总计数.但这给了我N + 1的问题.
public function sumPart($project_id)
{
$parts = DB::table('project_part')
->where('project_id', $project_id)
->where('part_id', $this->id)
->sum('count');
return $parts;
}
Run Code Online (Sandbox Code Playgroud)
chu*_*gbo 18
尝试总结Collection,
$project->parts->sum('pivot.count');
Run Code Online (Sandbox Code Playgroud)
这是我找到的最佳方式.它很干净(易于阅读),能够在parts多对多定义中重复使用所有范围,排序和关系属性缓存.
@hebron没有N + 1个问题该解决方案,如果您使用with('parts')到渴望负荷.因为$project->parts(没有函数调用)是一个缓存属性,所以返回一个包含所有数据的Collection实例.并且sum('pivot.count')是一种Collection包含纯函数助手的方法(不相对于数据库,如js世界中的下划线).
完整示例:
关系部分的定义:
class Project extends Model
{
public function parts()
{
return $this->belongsToMany('Part', 'project_part', 'project_id', 'part_id')
->withPivot('count')
->withTimestamps();
}
}
Run Code Online (Sandbox Code Playgroud)
当你使用它时(注意,急切的负载对于避免N + 1问题很重要),
App\Project::with('parts')->get()->each(function ($project) {
dump($project->parts->sum('pivot.count'));
});
Run Code Online (Sandbox Code Playgroud)
或者您可以在Project.php中定义sum函数,
class Project extends Model
{
...
/**
* Get parts count.
*
* @return integer
*/
public function partsCount()
{
return $this->parts->sum('pivot.count');
}
}
Run Code Online (Sandbox Code Playgroud)
如果要避免with('parts')在调用方(默认情况下是急切的加载部分),可以添加$with属性
class Project extends Model
{
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = ['parts'];
...
}
Run Code Online (Sandbox Code Playgroud)
从代码源:
我们需要使用"pivot_"前缀对所有枢轴列进行别名,以便我们可以轻松地将它们从模型中提取出来,并在检索并融入模型时将它们置于枢轴关系中.
所以你可以用select方法做同样的事情
public function parts()
{
return $this->belongsToMany('Part', 'project_part', 'project_id', 'part_id')
->selectRaw('parts.*, sum(project_part.count) as pivot_count')
->withTimestamps()
->groupBy('project_part.pivot_part_id')
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11644 次 |
| 最近记录: |