Laravel Eloquent关联统计:如何统计项目下所有任务的命令总数?
问题描述
数据表及Laravel模型关联关系为:projects -> tasks -> commands
统计任务数量的Eloquent代码如下,运行正常:
$projects = Project::withCount('tasks')->get();
现在需要统计所有任务对应的命令总数,对应的SQL语句为:
select count(commands.*) from projects inner join tasks on tasks.project_id = projects.id inner join commands on commands.task_id = tasks.id
请问如何使用Eloquent实现该统计?因某些原因无法使用Query Builder。遗憾的是,withCount不像with那样灵活,无法通过withCount('tasks.commands')实现需求。
实现方案
方法1:利用hasManyThrough关联 + withCount
首先在Project模型中定义与Command的hasManyThrough关联:
// app/Models/Project.php public function commands() { return $this->hasManyThrough(Command::class, Task::class); }
之后直接通过withCount统计:
$projects = Project::withCount('commands')->get();
每个Project实例会携带commands_count属性,对应该项目下所有任务的命令总数,底层生成的SQL逻辑和你给出的一致。
方法2:withCount嵌套闭包统计
如果不想新增关联,可在tasks的withCount闭包里嵌套统计命令数并求和:
$projects = Project::withCount(['tasks' => function ($query) { $query->withCount('commands')->selectRaw('sum(commands_count) as commands_total'); }])->get();
获取数据时,通过$project->tasks_commands_total拿到命令总数,$project->tasks_count仍保留任务数量。
方法3:模型访问器统计
在Project模型中添加访问器直接计算命令总数:
// app/Models/Project.php public function getCommandsTotalAttribute() { return $this->tasks()->sum('commands_count'); }
使用前需预先加载任务的命令统计避免N+1问题:
$projects = Project::with(['tasks' => function ($query) { $query->withCount('commands'); }])->get(); // 访问统计值 foreach ($projects as $project) { echo $project->commands_total; }
内容的提问来源于stack exchange,提问作者vbulash
相关产品推荐
相关产品推荐

