Laravel中如何通过关联关系批量更新数组中的多条记录
批量更新HasMany关联的BookingCostCalculation模型
我已经成功更新了Booking模型,但不知道如何更新与其关联的BookingCostCalculation模型(两者为hasMany关联)。之前存储数据时用的是createMany方法,现在需要批量更新关联数据。
请求数据
{ "booking": { "package_id": 4, "package_name": "masti ", "first_name": "shubham", "last_name": "pradhan", "email": "jioyhgjvn@gmail.com", "cc_email":"jio1@gmail.com,jio2@gmail.com", "phone": 9890989898, "total_pax": "5", "total_cost": "5000", "total_discount": "5000", "total_gst": "5000", "total_amount_to_pay": "3000", "comment":"hiii", "cost": [ { "package_itinerary_id": "1", "travel_mode_id": 1, "occupancy_id": 1, "package_price": 10000, "package_discount": 500 }, { "package_itinerary_id": "1", "travel_mode_id": 1, "occupancy_id": 1, "package_price": 10000, "package_discount": 500 } ] } }
当前控制器代码
$Booking = Booking::find($id); $bookingData = $request->booking; $Booking->update($bookingData); // dd($bookingData['cost']); if (is_array($bookingData['cost'])) { $Booking->BookingCostCalculation()->update([$bookingData['cost']]); }
解决方案
核心前提
批量更新关联记录的关键是每条记录必须包含主键id,这样才能精准匹配数据库中已有的BookingCostCalculation记录。如果前端请求的cost数组没有携带id,需要先调整前端传递该字段,或采用替代方案。
方案1:删旧建新(简单直接,无需保留旧记录ID)
如果不需要保留原有关联记录的ID,可以先清空旧数据,再用createMany重新创建:
$Booking = Booking::find($id); $bookingData = $request->booking; // 更新主模型 $Booking->update($bookingData); // 清空旧关联记录,创建新记录 if (is_array($bookingData['cost'])) { $Booking->BookingCostCalculation()->delete(); $Booking->BookingCostCalculation()->createMany($bookingData['cost']); }
方案2:用upsert批量更新/插入(Laravel 8+推荐)
如果前端能传递每条cost记录的id,可以用upsert实现"存在则更新,不存在则插入"的逻辑:
$Booking = Booking::find($id); $bookingData = $request->booking; $Booking->update($bookingData); if (is_array($bookingData['cost'])) { $Booking->BookingCostCalculation()->upsert( $bookingData['cost'], ['id'], // 唯一匹配的主键字段 ['package_itinerary_id', 'travel_mode_id', 'occupancy_id', 'package_price', 'package_discount'] // 需要更新的字段列表 ); }
方案3:循环匹配更新(无ID时的妥协方案)
如果无法获取id,只能依赖记录顺序与现有数据一致,可以逐个循环更新:
$Booking = Booking::find($id); $bookingData = $request->booking; $Booking->update($bookingData); if (is_array($bookingData['cost'])) { $existingCosts = $Booking->BookingCostCalculation()->get(); foreach ($existingCosts as $index => $cost) { // 按顺序匹配更新,注意:若记录数量不匹配会遗漏或报错 if (isset($bookingData['cost'][$index])) { $cost->update($bookingData['cost'][$index]); } } }
原代码问题说明
你当前的$Booking->BookingCostCalculation()->update([$bookingData['cost']]);写法错误,update()方法接收的是单个键值对数组(用于将所有关联记录更新为同一值),而非数组的数组,因此无法实现批量更新不同记录的需求。
内容的提问来源于stack exchange,提问作者Shubham Rana
相关产品推荐
相关产品推荐

