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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 23:12:18