Laravel多表取数按星期分组并生成指定格式数组的问题
解决Laravel多表数据按星期+屏幕分组的需求
看起来你已经有了初步思路,我来帮你完善这个实现,正好匹配你想要的day1[screen1[], screen2[]]这样的数组结构。
核心需求梳理
- 获取未来7天的电影排片数据
- 按**天数(day1到day7)**分组
- 每个天数下再按**屏幕(screen1、screen2...)**分组,存储对应屏幕当天的排片记录
优化后的实现方案(两种可选)
方案1:循环查询(逻辑直观,适合小数据量场景)
这种方式代码易懂,适合快速上手:
use Carbon\Carbon; use App\Models\Screen; use App\Models\ScheduledMovie; // 提前获取所有屏幕ID,避免循环内重复查询数据库(性能优化) $screenIds = Screen::pluck('id')->toArray(); $finalArray = []; for ($i = 0; $i < 7; $i++) { // 计算当前偏移i天的日期和星期信息 $currentDate = Carbon::now()->addDays($i); $formattedDate = $currentDate->format('Y-m-d'); $dayName = $currentDate->format('l'); // 可选:如果需要星期英文名称(如Monday) // 初始化当天的屏幕数据容器 $dailyScreenData = []; // 遍历每个屏幕,查询对应排片 foreach ($screenIds as $screenId) { $showTimes = ScheduledMovie::where('movie_id', $id) ->where('show_date', $formattedDate) ->where('screen_id', $screenId) // 如果show_day是冗余字段(从show_date生成),建议去掉该条件以简化查询 // ->where('show_day', $dayName) ->get() ->toArray(); // 转成数组,也可保留Collection按需处理 // 按screen1、screen2的格式命名键 $dailyScreenData["screen{$screenId}"] = $showTimes; } // 把当天数据加入最终数组,键为day1、day2... $finalArray["day".($i + 1)] = $dailyScreenData; } // 查看最终结构 dd($finalArray);
方案2:批量查询+内存分组(性能更优,适合大数据量场景)
如果屏幕数量多或排片数据量大,推荐这种方式——仅需2次数据库查询,避免循环内多次请求:
use Carbon\Carbon; use App\Models\Screen; use App\Models\ScheduledMovie; // 定义时间范围:未来7天 $startDate = Carbon::now(); $endDate = Carbon::now()->addDays(6); // 一次性查询所有符合条件的排片数据 $scheduledMovies = ScheduledMovie::where('movie_id', $id) ->whereBetween('show_date', [ $startDate->format('Y-m-d'), $endDate->format('Y-m-d') ]) ->get(); // 获取所有屏幕ID $screenIds = Screen::pluck('id')->toArray(); $finalArray = []; for ($i = 0; $i < 7; $i++) { $currentDate = $startDate->copy()->addDays($i); $formattedDate = $currentDate->format('Y-m-d'); $dayKey = "day".($i + 1); $finalArray[$dayKey] = []; // 遍历屏幕,从已查询的集合中筛选数据 foreach ($screenIds as $screenId) { $screenShowTimes = $scheduledMovies->filter(function ($item) use ($formattedDate, $screenId) { return $item->show_date === $formattedDate && $item->screen_id === $screenId; })->toArray(); $finalArray[$dayKey]["screen{$screenId}"] = $screenShowTimes; } } dd($finalArray);
关键优化说明
- 减少重复查询:把
Screen::pluck('id')提到循环外,避免多次请求数据库 - 简化日期处理:直接用Carbon对象的方法操作日期,无需手动转时间戳
- 灵活键命名:如果想用星期名称(如
Monday)代替day1,只需把"day".($i+1)改成$dayName即可 - 冗余字段处理:若
show_day是从show_date生成的冗余字段,建议去掉该查询条件,简化筛选逻辑
内容的提问来源于stack exchange,提问作者Binod Paneru
相关产品推荐
相关产品推荐

