Laravel Eloquent:按项目状态统计未来12个月每月计划工时
解决方案:按项目状态统计未来12个月每月计划工时总和
1. 补充模型关联(若未定义)
确保各模型间的关联关系正确配置:
// Project.php public function projectUsers() { return $this->hasMany(ProjectUser::class); } // ProjectUser.php public function project() { return $this->belongsTo(Project::class); } public function schedules() { return $this->hasMany(Schedule::class); } // Schedule.php public function week() { return $this->belongsTo(Week::class); } public function projectUser() { return $this->belongsTo(ProjectUser::class); }
2. 生成未来12个月的年月范围
从当前月份开始,生成后续12个月的年份、月份数组,用于后续筛选和结果映射:
$months = []; $currentDate = now(); for ($i = 0; $i < 12; $i++) { $months[] = [ 'year' => $currentDate->year, 'month' => $currentDate->month ]; $currentDate->addMonth(); }
3. 关联查询并统计工时
通过多表关联,按年月、项目状态分组,统计计划工时总和:
$stats = Schedule::query() ->join('project_users', 'schedules.project_user_id', '=', 'project_users.id') ->join('projects', 'project_users.project_id', '=', 'projects.id') ->join('weeks', 'schedules.week_id', '=', 'weeks.id') ->whereIn('weeks.year', collect($months)->pluck('year')) ->whereIn('weeks.month', collect($months)->pluck('month')) ->selectRaw('weeks.year, weeks.month, projects.status, SUM(schedules.planned_hours) as total_planned') ->groupBy('weeks.year', 'weeks.month', 'projects.status') ->get() ->keyBy(function ($item) { return $item->year . '-' . $item->month; });
4. 整理为目标格式数组
将统计结果映射到未来12个月的索引位置,生成要求的数组结构:
$result = []; foreach ($months as $index => $month) { $key = $month['year'] . '-' . $month['month']; $monthStats = $stats->get($key); $statusTotals = []; if ($monthStats) { foreach ($monthStats as $stat) { $statusTotals[$stat->status] = $stat->total_planned; } } $result[$index] = $statusTotals; } // 输出即为目标格式 dd($result);
补充说明
- 若需默认显示所有状态(无工时则为0),可先查询所有项目状态,遍历填充默认值;
- 确保Week模型的
year和month字段为整数类型,避免统计偏差; - 可根据业务需求添加额外筛选条件(如排除已结束项目)。
内容的提问来源于stack exchange,提问作者Cornel Verster
相关产品推荐
相关产品推荐

