Laravel下单成功后如何扣减数据库中对应图书的库存数量
实现下单自动扣减图书库存方案
你的数据库截图:
一、接口参数调整
首先需要让前端在调用orderSuccessfull下单接口时,额外传递两个参数:
- 购买的图书ID:
book_id(示例中对应值为1) - 购买数量:
buy_count(示例中对应值为1)
二、修改CustomerController.php的orderSuccessfull方法
核心逻辑增加数据库事务,保证订单创建和库存扣减的原子性,同时增加库存校验逻辑避免超卖,修改后代码如下:
public function orderSuccessfull(Request $request){ // 前置校验必填参数合法性 $request->validate([ 'book_id' => 'required|integer|exists:books,id', 'buy_count' => 'required|integer|min:1' ]); // 开启事务:订单创建和库存扣减操作会同时成功/失败,避免数据不一致 return DB::transaction(function () use ($request) { $cust=new Customers(); $cust->user_id = auth()->id(); $cust_id=Customers::where('user_id',$cust->user_id)->value('user_id'); $user_email=User::where('id',$cust_id)->value('email'); $order = User::where('email', $user_email)->first(); $ord = Orders::create( [ 'orderNumber' => $order->orderNumber=mt_rand(1000000000, 9999999999), 'customer_id'=>$order->id, 'order_date'=>$order->order_date=Carbon::now(), // 如果你的orders表需要关联对应图书,可保留这行,不需要直接删除即可 'book_id' => $request->book_id ] ); // 库存扣减逻辑 $buyCount = $request->buy_count; $book = ModelsBooks::where('id', $request->book_id) // 给查询到的图书记录加行锁,防止并发下单时出现超卖 ->lockForUpdate() ->first(); if (!$book || $book->quantity < $buyCount) { throw new \Exception('当前图书库存不足,下单失败'); } // 执行库存扣减 $book->decrement('quantity', $buyCount); if($order && $ord){ $order->notify(new orderSuccessfullNotification($ord->orderNumber)); } return response()->json(['message'=>'order created successfully','OrderId'=>$ord->orderNumber]); }); }
三、逻辑说明
- 参数校验层提前拦截非法请求,避免后续逻辑出错
- 事务包裹所有关联操作,杜绝出现订单创建成功但库存未扣、或者库存扣减成功但订单未生成的异常情况
- 行锁+库存前置校验的组合方案,完全避免并发下单场景下的超卖问题
- 使用Laravel原生的
decrement方法实现库存字段自减,语法简洁兼容性好
四、多图书购买扩展(可选)
如果后续需要支持一个订单购买多本图书,你需要额外创建order_items订单明细表,存储每个订单关联的图书ID、对应购买数量,扣库存时遍历所有购买的图书逐一校验扣减即可。
内容的提问来源于stack exchange,提问作者user16172211
相关产品推荐
相关产品推荐


