Laravel中如何将多个商品详情存储到数据库的同一行?
Hey, let’s get this order storage issue sorted out quickly since your site’s live. The core problem here is that your current code isn’t creating a single parent Order record for the entire checkout, and you’re mishandling how OrderDetail entries are saved for each product. Let’s fix that step by step.
Key Issues in Your Original Code
- No main
Orderrecord being created (you reference$orderbut never initialize it) OrderDetailis only saved once instead of per product- Incorrect assignment of
seller_id(you tried saving the entire$seller_productsarray instead of the actual seller ID) - Undefined total variables (like
$subtotal) that would throw errors - Stock validation logic was mispositioned
Fixed Controller Code
public function store(Request $request) { $carts = Cart::where('user_id', Auth::user()->id)->get(); if ($carts->isEmpty()) { flash(translate('Your cart is empty'))->warning(); return redirect()->route('home'); } // Initialize totals to avoid undefined variable errors $subtotal = 0; $tax = 0; $coupon_discount = 0; $shipping = 0; // Get and update shipping info $shipping_info = Address::where('id', $carts->first()->address_id)->first(); $shipping_info->name = Auth::user()->name; $shipping_info->email = Auth::user()->email; if ($shipping_info->latitude && $shipping_info->longitude) { $shipping_info->lat_lang = "{$shipping_info->latitude},{$shipping_info->longitude}"; } $shipping_info->save(); // Group cart items by seller (cleaned up) $seller_products = []; foreach ($carts as $cartItem) { $product = Product::findOrFail($cartItem->product_id); $sellerId = $product->user_id; if (!isset($seller_products[$sellerId])) { $seller_products[$sellerId] = []; } $seller_products[$sellerId][] = $cartItem; } // Create the main Order record (critical missing piece!) $order = new Order(); $order->user_id = Auth::user()->id; $order->address_id = $shipping_info->id; $order->status = 'pending'; // Adjust to your default status // Add other required order fields here (payment method, etc.) $order->save(); // Save OrderDetail entries for each product foreach ($seller_products as $sellerId => $sellerCartItems) { foreach ($sellerCartItems as $cartItem) { $product = Product::findOrFail($cartItem->product_id); $product_variation = $cartItem->variation; $product_stock = $product->stocks->where('variant', $product_variation)->first(); // Validate stock availability if ($product->digital != 1 && (!$product_stock || $cartItem->quantity > $product_stock->qty)) { flash(translate('The requested quantity is not available for ') . $product->getTranslation('name'))->warning(); $order->delete(); // Clean up incomplete order return redirect()->route('cart'); } // Deduct stock for physical products if ($product->digital != 1) { $product_stock->qty -= $cartItem->quantity; $product_stock->save(); } // Calculate line item values $lineSubtotal = $cartItem->price * $cartItem->quantity; $lineTax = $cartItem->tax * $cartItem->quantity; // Update order totals $subtotal += $lineSubtotal; $tax += $lineTax; $coupon_discount += $cartItem->discount; $shipping += $cartItem->shipping_cost; // Create and save individual OrderDetail $order_detail = new OrderDetail(); $order_detail->order_id = $order->id; $order_detail->seller_id = $sellerId; // Correct seller ID $order_detail->product_id = $product->id; $order_detail->variation = $product_variation; $order_detail->price = $cartItem->price; // Store unit price $order_detail->tax = $cartItem->tax; // Store unit tax $order_detail->shipping_type = $cartItem->shipping_type; $order_detail->product_referral_code = $cartItem->product_referral_code; $order_detail->shipping_cost = $cartItem->shipping_cost; $order_detail->quantity = $cartItem->quantity; if ($cartItem->shipping_type == 'pickup_point') { $order_detail->pickup_point_id = $cartItem->pickup_point; } $order_detail->save(); } } // Update main order with final calculated totals $order->subtotal = $subtotal; $order->tax = $tax; $order->coupon_discount = $coupon_discount; $order->shipping_cost = $shipping; $order->total = $subtotal + $tax + $shipping - $coupon_discount; $order->save(); flash(translate('Order placed successfully!'))->success(); return redirect()->route('orders.index'); // Adjust to your orders listing route }
Critical Fixes Explained
- Single Parent Order: We now create one
Orderrecord first, which all product-specificOrderDetailentries link to viaorder_id—this ensures one order per checkout. - Per-Product OrderDetails: Nested loops iterate through each seller’s products, creating a separate
OrderDetailfor every item in the cart. - Valid Seller ID: We use the actual seller ID from the grouped products instead of saving an array (which would store invalid data).
- Error Prevention: Initialized total variables and used
findOrFailto catch missing products early. - Accurate Totals: Final order totals are calculated after processing all items and saved back to the main order record.
Before Deploying
Test this on a staging environment first! Verify:
- One
orderstable entry per checkout - Multiple
order_detailsentries linked to the sameorder_id - Stock levels are correctly deducted for physical products
- Totals match the checkout summary
内容的提问来源于stack exchange,提问作者Memo11
相关产品推荐
相关产品推荐

