1.当购物车提交时,POST传来一个对象{address:2,item:{ {ksu_id:2,count:2},{ksu_id:2,count:2}, }
验证方法:
public function rules() { return [ // 判断用户提交的地址 ID 是否存在于数据库并且属于当前用户 // 后面这个条件非常重要,否则恶意用户可以用不同的地址 ID 不断提交订单来遍历出平台所有用户的收货地址 'address_id' => [ 'required', Rule::exists('user_addresses', 'id')->where('user_id', $this->user()->id), ], 'items' => ['required', 'array'], 'items.*.sku_id' => [ // 检查 items 数组下每一个子数组的 sku_id 参数 'required', function ($attribute, $value, $fail) { if (!$sku = ProductSku::find($value)) { return $fail('该商品不存在'); } if (!$sku->product->on_sale) { return $fail('该商品未上架'); } if ($sku->stock === 0) { return $fail('该商品已售完'); } // 获取当前索引 preg_match('/items.(d+).sku_id/', $attribute, $m); $index = $m[1]; // 根据索引找到用户所提交的购买数量 $amount = $this->input('items')[$index]['amount']; if ($amount > 0 && $amount > $sku->stock) { return $fail('该商品库存不足'); } }, ], 'items.*.amount' => ['required', 'integer', 'min:1'], ]; } } 在检查 sku_id 时我们依然判断了对应 SKU 是否存在、商品是否上架、库存是否充足,因为用户在把商品加入购物车,再到下单时商品的各个状态都可能发生变化。 在检查库存时,我们需要获取用户想要购买的该 SKU 数量,我们可以通过匿名函数的第一个参数 $attribute 来获取当前 SKU 所在的数组索引,比如第一个 SKU 的 $attribute 就是 items.0.sku_id,所以我们采用正则的方式将这个 0 提取出来,$this->input('items')[0]['amount'] 就是用户想购买的数量。 接下来我们来写具体的创建订单逻辑: app/Http/Controllers/OrdersController.php <?php namespace AppHttpControllers; use AppHttpRequestsOrderRequest; use AppModelsProductSku; use AppModelsUserAddress; use AppModelsOrder; use CarbonCarbon; class OrdersController extends Controller { public function store(OrderRequest $request) { $user = $request->user(); // 开启一个数据库事务 $order = DB::transaction(function () use ($user, $request) { $address = UserAddress::find($request->input('address_id')); // 更新此地址的最后使用时间 $address->update(['last_used_at' => Carbon::now()]); // 创建一个订单 $order = new Order([ 'address' => [ // 将地址信息放入订单中 'address' => $address->full_address, 'zip' => $address->zip, 'contact_name' => $address->contact_name, 'contact_phone' => $address->contact_phone, ], 'remark' => $request->input('remark'), 'total_amount' => 0, ]); // 订单关联到当前用户 $order->user()->associate($user); // 写入数据库 $order->save(); $totalAmount = 0; $items = $request->input('items'); // 遍历用户提交的 SKU foreach ($items as $data) { $sku = ProductSku::find($data['sku_id']); // 创建一个 OrderItem 并直接与当前订单关联 $item = $order->items()->make([ 'amount' => $data['amount'], 'price' => $sku->price, ]); $item->product()->associate($sku->product_id); $item->productSku()->associate($sku); $item->save(); $totalAmount += $sku->price * $data['amount']; } // 更新订单总金额 $order->update(['total_amount' => $totalAmount]); // 将下单的商品从购物车中移除 $skuIds = collect($items)->pluck('sku_id'); $user->cartItems()->whereIn('product_sku_id', $skuIds)->delete(); return $order; }); return $order; }