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

Laravel中向两张表插入记录并同步更新store_inventories表库存的问题

问题需求

在Laravel中提交数据时同步完成两个操作:向store_inventory_entries表插入入库记录,同时更新store_inventories表对应商品的stock库存字段,两张表通过inventory_id关联。
表结构参考:
表结构示意图

现有代码参考

控制器实现代码

public function saveInventoryEntry(Request $request)
{
    $message = null; 
   
    $data = $request->all();
    $ids= [];

    try {
        foreach ($data as $key => $inventory) {
            
            $inventoryEntry = new StoreInventoryEntry();
            $inventoryEntry->inventory_id = $inventory['id'];
            $inventoryEntry->code = $inventory['code'];
            $inventoryEntry->quantity = $inventory['quantity'];
            $inventoryEntry->save();

            $ids[] = $inventory['id']; 
           
            StoreInventory::whereIn('id',$dt)->update(['stock' => $inventory['quantity']]);
                           
        }
        
        $message = $this->sendResponse($inventoryEntry, 'Aggregated data');

    } catch (\Exception $e) {
        $message = $this->sendError($e->getMessage(), ['Entries could not be registered'], 500);
    }

    return $message;

}

提交数据格式

[
 {
    "id" : 1,
    "code" : "010101",       
    "quantity" : 10 
 },
 {
    "id" : 2,
    "code" : "23232",       
    "quantity" : 7 
 }
]

迁移文件代码

// store_inventories 表迁移
public function up()
{
    Schema::create('store_inventories', function (Blueprint $table) {
        $table->id();
        $table->string('code');
        $table->string('reference');
        $table->string('line');
        $table->integer('cost');
        $table->integer('stock');
        $table->integer('min_stock');
        $table->string('location')->default('Almacén');
        $table->boolean('status')->default(1);
        $table->timestamps();
    });
}

// store_inventory_entries 表迁移
public function up()
{
    Schema::create('store_inventory_entries', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('inventory_id');
        $table->string('code');
        $table->integer('quantity');
        $table->foreign('inventory_id')->references('id')->on('store_inventories');
        $table->timestamps();
    });
}
问题排查与修复方案

原有代码存在两个核心问题:

  • 代码中StoreInventory::whereIn('id',$dt)里的$dt变量未定义,会直接触发报错
  • 即使给$dt赋值,每次循环用whereIn批量更新库存,会导致所有已遍历过的商品库存都被覆盖为当前循环的quantity值,逻辑完全错误

正确实现代码

建议开启数据库事务,保证入库记录插入和库存更新两个操作的原子性,避免出现数据不一致的情况。

use Illuminate\Support\Facades\DB;

public function saveInventoryEntry(Request $request)
{
    try {
        $data = $request->all();
        $lastEntry = null;

        DB::transaction(function () use ($data, &$lastEntry) {
            foreach ($data as $inventory) {
                // 插入入库记录
                $lastEntry = StoreInventoryEntry::create([
                    'inventory_id' => $inventory['id'],
                    'code' => $inventory['code'],
                    'quantity' => $inventory['quantity'],
                ]);

                // 更新对应商品库存,二选一即可
                // 场景1:直接覆盖库存为提交的quantity值
                StoreInventory::where('id', $inventory['id'])
                    ->update(['stock' => $inventory['quantity']]);
                
                // 场景2:入库累加库存(入库业务推荐使用,自带行锁避免并发更新问题)
                // StoreInventory::where('id', $inventory['id'])
                //     ->increment('stock', $inventory['quantity']);
            }
        });

        return $this->sendResponse($lastEntry, '库存录入成功');
    } catch (\Exception $e) {
        return $this->sendError($e->getMessage(), ['库存录入失败'], 500);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:24:10