Laravel 8多对多关系下自动关联周日期与营业时间方案问询
多对多关联绑定失败修复方案
问题根因
insert()是 Laravel 查询构造器的批量插入方法,执行后仅返回布尔值标识插入是否成功,不会返回插入的模型实例或主键ID集合,因此你后续调用$daysweek->schedule()会直接报错,此时$daysweek不是模型对象,只是布尔值。- 你当前的写法即使拿到了ID集合,直接
sync也只会把所有时间表ID绑定到同一个星期记录,无法实现「周一对应第一个营业时间、周二对应第二个营业时间」的一一对应绑定需求。
解决方案
方案一:循环创建逐个关联(推荐)
按顺序创建星期记录后直接绑定对应营业时间,不会出现ID错乱问题:
public function createShop() { $schedules = [ ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ]; $daysweeks = [ ['name' => 'Segunda-Feira'], ['name' => 'Terça-Feira'], ['name' => 'Quarta-Feira'], ['name' => 'Quinta-Feira'], ['name' => 'Sexta-Feira'], ['name' => 'Sábado'], ['name' => 'Domingo'], ]; foreach ($daysweeks as $index => $dayData) { // 创建星期记录 $day = DaysWeek::create($dayData); // 创建对应顺序的营业时间并完成关联 $day->schedule()->create($schedules[$index]); } }
方案二:批量插入后按顺序关联(适合数据量较大的场景)
如果需要优化插入性能,可先批量插入后获取主键ID再按顺序绑定,注意要保证插入期间没有其他请求同时写入这两张表避免ID错乱:
public function createShop() { $schedules = [ ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ['start' => now(),'end' => now()], ]; $daysweeks = [ ['name' => 'Segunda-Feira'], ['name' => 'Terça-Feira'], ['name' => 'Quarta-Feira'], ['name' => 'Quinta-Feira'], ['name' => 'Sexta-Feira'], ['name' => 'Sábado'], ['name' => 'Domingo'], ]; // 批量插入营业时间,获取插入后的ID集合 $lastScheduleId = Schedules::max('id') ?? 0; Schedules::insert($schedules); $scheduleIds = Schedules::where('id', '>', $lastScheduleId) ->orderBy('id') ->pluck('id') ->toArray(); // 批量插入星期记录,获取插入后的ID集合 $lastDayId = DaysWeek::max('id') ?? 0; DaysWeek::insert($daysweeks); $dayIds = DaysWeek::where('id', '>', $lastDayId) ->orderBy('id') ->pluck('id') ->toArray(); // 按顺序一一对应绑定关联 foreach ($dayIds as $index => $dayId) { $day = DaysWeek::find($dayId); $day->schedule()->sync([$scheduleIds[$index]]); } }
注意事项
- 首先要确保你的
DaysWeek模型已经正确定义了多对多关联的schedule()方法,中间表、外键、关联键的配置都要正确。 - 如果你的业务场景里一个星期只对应一个营业时间,其实不需要用多对多关联,直接用一对多更合理:在星期表加个
schedule_id字段关联营业时间表即可,逻辑更简单。
内容的提问来源于stack exchange,提问作者Nietore
相关产品推荐
相关产品推荐

