You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

关键优化说明

  1. 减少重复查询:把Screen::pluck('id')提到循环外,避免多次请求数据库
  2. 简化日期处理:直接用Carbon对象的方法操作日期,无需手动转时间戳
  3. 灵活键命名:如果想用星期名称(如Monday)代替day1,只需把"day".($i+1)改成$dayName即可
  4. 冗余字段处理:若show_day是从show_date生成的冗余字段,建议去掉该查询条件,简化筛选逻辑

内容的提问来源于stack exchange,提问作者Binod Paneru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:01:40