在Laravel 4中;我有模型Project
和Part
,它们与数据透视表project_part
具有多对多关系。数据透视表的列count
包含项目中使用的零件ID的编号,例如:
id project_id part_id count
24 6 230 3
[这里project_id
6,正在使用3个part_id
230。
一个项目可能多次列出一个部分,例如:
id project_id part_id count
24 6 230 3
92 6 230 1
当我显示项目的零件清单时,我不想重复显示part_id
,因此我将结果分组。
我的[[Projects模型具有此:
public function parts()
{
return $this->belongsToMany('Part', 'project_part', 'project_id', 'part_id')
->withPivot('count')
->withTimestamps()
->groupBy('pivot_part_id')
}
但是我的意味着我的count
值当然不正确,这是我的问题:如何获得项目的所有分组部分的总和?
project_id
6零件清单应类似于:part_id count
230 4
我非常想以作为临时的解决方法,我创建了一个presenter方法来获取项目中的总零件数。但这给了我N + 1的问题。Projects
-Parts
关系使用它,因此我急切地希望加载它。如果不解决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;
}
我们需要为所有枢轴列都加上别名“ 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')
}
Collection
中求和,$project->parts->sum('pivot.count');
这是我发现的最好方法。它很干净(易于阅读),并且可以在parts
多对多定义中重新使用所有范围,顺序和关系属性缓存。@ hebron如果使用
with('parts')
至eager load,则此解决方案没有N + 1问题。由于$project->parts
(without函数调用)是缓存的属性,因此请返回Collection的实例以及所有数据。
完整示例:sum('pivot.count')
是Collection
的一种方法,它包含纯函数助手(与js world中的underscore无关,与数据库无关)。相关部分的定义:
class Project extends Model { public function parts() { return $this->belongsToMany('Part', 'project_part', 'project_id', 'part_id') ->withPivot('count') ->withTimestamps(); } }
[使用时(注意,急切的加载对于避免N + 1问题很重要),
App\Project::with('parts')->get()->each(function ($project) { dump($project->parts->sum('pivot.count')); });
或者您可以在Project.php中定义sum函数,
class Project extends Model { ... /** * Get parts count. * * @return integer */ public function partsCount() { return $this->parts->sum('pivot.count'); } }
如果要避免在呼叫方使用with('parts')
(默认情况下为紧急加载部分,则可以添加$with
属性
class Project extends Model { /** * The relations to eager load on every query. * * @var array */ protected $with = ['parts']; ... }
$project->parts->sum('pivot.count');
我遇到了同样的问题,但这解决了我的问题。