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

Laravel训练计划:周/日/训练动作关联与workout_id绑定问题

解决训练计划多对多关联绑定workout_id的问题

核心问题梳理

你的代码存在几个关键问题,导致无法正确将workout_id绑定到多对多关联中:

  • 周关联逻辑错误:直接用Week::find($j)查找周记录不合理,$j是训练计划的周数序号,并非Week表的主键;且循环中重复执行sync会覆盖之前的关联。
  • 请求参数获取方式错误:$request->week_.$j.'_day_1'的写法无法正确读取请求参数,需使用Laravel标准的input方法。
  • 多对多中间表字段传递错误:sync方法的参数格式不正确,未正确携带workout_id到关联中间表。

修正后的完整代码

public function store(Request $request)
{
    try {
        $this->validate($request, [
            "title"         => "required|unique:workouts",
            "description"   => "required",
            "goal_id"       => "required",
            "level_id"      => "required",
            "duration"      => "required",
            "status"        => "required"
        ]);
        
        $image = null;
        if($request->hasFile('image')) {
            $image = Cloudinary::upload($request->file('image')->getRealPath())->getSecurePath();
        }

        // 创建训练计划主记录
        $workout = Workout::create([
            "title"         => $request->title,
            "description"   => $request->description,
            "goal_id"       => $request->goal_id,
            "level_id"      => $request->level_id,
            "duration"      => $request->duration,
            "image"         => $image,
            "price"         => $request->price,
            "status"        => $request->status
        ]);

        // 关联身体部位和器材
        $workout->workout_bodypart()->sync($request->bodyparts);
        $workout->workout_equipment()->sync($request->equipments);

        // 处理每周的关联与天数配置
        for($weekNum = 1; $weekNum <= $request->duration; $weekNum++) {
            // 创建或获取当前训练计划对应的周记录(假设Week表用number字段存储周序号)
            $week = Week::firstOrCreate([
                'number' => $weekNum
            ]);

            // 关联训练计划与周
            $workout->workout_week()->syncWithoutDetaching([$week->id]);

            // 遍历7天,处理每天的训练动作关联
            for($dayNum = 1; $dayNum <= 7; $dayNum++) {
                // 获取当天的训练动作ID数组
                $exerciseIds = $request->input("week_{$weekNum}_day_{$dayNum}", []);
                
                // 休息日无动作,直接跳过
                if(empty($exerciseIds)) continue;

                // 创建或获取天记录(假设Day表用number字段存储天序号)
                $day = Day::firstOrCreate([
                    'number' => $dayNum
                ]);

                // 关联周与天,同时绑定workout_id到中间表
                $week->week_day()->syncWithoutDetaching([
                    $day->id => ['workout_id' => $workout->id]
                ]);

                // 关联天与训练动作,绑定workout_id到中间表
                $day->day_exercise()->syncWithoutDetaching(
                    collect($exerciseIds)->mapWithKeys(function($exerciseId) use ($workout) {
                        return [$exerciseId => ['workout_id' => $workout->id]];
                    })->toArray()
                );
            }
        }

        return redirect()->route('workouts.index')->with('success', "训练计划添加成功!");
    } catch(Exception $e) {
        return redirect()->back()->with('error', $e->getMessage());
    }
}

关键修正说明

  1. 周/天记录的创建逻辑:用firstOrCreate确保每个周/天序号对应的记录存在,避免直接用主键查找的错误。
  2. 关联方式优化:使用syncWithoutDetaching避免覆盖已有的关联,适配多对多场景的增量关联需求。
  3. 请求参数正确读取:通过$request->input("week_{$weekNum}_day_{$dayNum}")正确获取对应周数天数的训练动作ID。
  4. 中间表字段传递:在sync时通过键值对形式,将workout_id附加到中间表,确保所有关联都绑定到当前训练计划。
  5. 休息日处理:当天无训练动作时直接跳过,符合你3天休息日的需求。

内容的提问来源于stack exchange,提问作者Sharada Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:31:03