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

Laravel一对多关联模型添加项成功但未写入数据库求助

问题描述

我一直卡在这个问题上。想通过Update方法从ShipmentRequest模型插入ShipmentRequestItem,以下是我的update方法代码:

public function update(UpdateShipmentRequestRequest $request, $id)
{
    $shipmentRequest = ShipmentRequest::with(
        'shipmentRequestItems',
        )->where('id',$id)->first();
    $shipmentRequest->update($request->all());
    $validatedData = $request->validated();
    $shipmentRequestItems = $validatedData['shipmentRequestItems'];
    // $shipmentRequest = ShipmentRequest::find($id);
    
    $existingItems = [];
    foreach ($shipmentRequestItems as $value) {
        DB::beginTransaction();
        if (is_array($value)) {
            $shipmentRequestItem = new ShipmentRequestItem;
            $shipmentRequestItem->name = $value["name"];
            $shipmentRequestItem->quantity = $value["quantity"];
            $shipmentRequestItem->shipment_request_id = $shipmentRequest->id;
    
            // Save the ShipmentRequestItem to the database
            $shipmentRequestItem->save();
            $shipmentRequest->shipmentRequestItems()->create(['name' => $value['name'], 'quantity'=> $value['quantity']]);
            $shipmentRequest->shipmentRequestItems()->save($shipmentRequestItem);
            echo json_encode($shipmentRequest);
            echo json_encode($shipmentRequestItem);
        } else {
            $existingItems[] = $value;
        }
    }
    
    $shipmentRequest->shipmentRequestItems()->whereNotIn('id', $existingItems)->delete();
    $shipmentRequest->refresh();
    return new ShipmentRequestResource($shipmentRequest);
}

输出$shipmentRequest->shipmentRequestItems()时显示项已成功添加,但数据库表中没有记录,且ID在递增。尝试多种插入方法结果都一样,数据未写入数据库。

解决方法

1. 核心问题:事务未提交

你在循环内开启了事务DB::beginTransaction();,但全程没有执行DB::commit();来提交事务。事务未提交时,所有数据库操作都只是临时的内存状态,不会真正写入数据库;而ID递增是因为自增字段在执行插入语句时就会被占用,不管事务最终是否提交。

2. 冗余操作:重复创建数据

同一个分支里执行了三次插入逻辑:

  • $shipmentRequestItem->save();
  • $shipmentRequest->shipmentRequestItems()->create(...)
  • $shipmentRequest->shipmentRequestItems()->save($shipmentRequestItem);
    这会导致重复生成多条相同记录,完全没必要,保留一种关联创建方式即可。

修正后的代码

public function update(UpdateShipmentRequestRequest $request, $id)
{
    DB::beginTransaction(); // 将事务放在循环外,避免多次开启
    try {
        $shipmentRequest = ShipmentRequest::with('shipmentRequestItems')->findOrFail($id);
        $shipmentRequest->update($request->all());
        
        $validatedData = $request->validated();
        $shipmentRequestItems = $validatedData['shipmentRequestItems'];
        
        $existingItems = [];
        foreach ($shipmentRequestItems as $value) {
            if (is_array($value)) {
                // 利用关联关系创建,自动处理外键赋值,无需手动设置shipment_request_id
                $shipmentRequest->shipmentRequestItems()->create([
                    'name' => $value['name'],
                    'quantity' => $value['quantity']
                ]);
            } else {
                $existingItems[] = $value;
            }
        }
        
        // 删除不在现有列表中的关联项
        if (!empty($existingItems)) {
            $shipmentRequest->shipmentRequestItems()->whereNotIn('id', $existingItems)->delete();
        } else {
            // 若没有保留的现有项,删除所有关联项
            $shipmentRequest->shipmentRequestItems()->delete();
        }
        
        $shipmentRequest->refresh();
        DB::commit(); // 提交事务,写入数据库
        return new ShipmentRequestResource($shipmentRequest);
    } catch (\Exception $e) {
        DB::rollBack(); // 发生异常时回滚事务
        throw $e; // 抛出异常,交由框架处理错误响应
    }
}

额外检查项

  • 确认ShipmentRequestItem模型的$fillable属性包含所需字段,否则批量赋值会失败:
class ShipmentRequestItem extends Model
{
    protected $fillable = ['name', 'quantity', 'shipment_request_id'];
}
  • 检查数据库连接配置,确保操作的是目标数据库;
  • 查看Laravel日志文件(storage/logs/laravel.log),排查是否有隐藏的异常信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:23:28