Laravel 7+AJAX购物车新增商品时foreach无法加载最新数据
搞定你的Laravel购物车AJAX渲染问题
嘿,兄弟,我一眼就看出问题出在哪了——你踩了Laravel Eloquent关联缓存的经典坑!
问题根源
当你第一次执行foreach ($order->orderItems as $key => $order_item)的时候,Laravel会自动查询数据库并把订单项的集合缓存到$order模型实例里。之后你创建了新的订单项,但再访问$order->orderItems时,它直接用的是之前缓存的旧数据,根本没去数据库查最新的内容,所以第一次添加新商品时渲染的HTML里没有这条新项。而第二次添加时,你是更新已有的订单项,缓存里本来就有这个条目,数量更新后能正常同步,所以就显示出来了。
解决方法(三种任选其一)
1. 单独重新加载orderItems关联
在创建新订单项之后,加一行代码强制重新从数据库加载订单项:
if ($bingo == false) { $new_item = new OrderItem(); $new_item->order_id = $order_id; $new_item->product_id = $product_id; $new_item->save(); // 关键:重新加载关联,拿到最新数据 $order->load('orderItems'); }
2. 刷新整个Order模型
如果想让整个$order模型都同步最新数据,也可以用refresh()方法:
if ($bingo == false) { $new_item = new OrderItem(); $new_item->order_id = $order_id; $new_item->product_id = $product_id; $new_item->save(); // 刷新整个模型,所有关联都会重新加载 $order->refresh(); }
3. 直接查询最新的订单项集合
另一种思路是绕过模型关联缓存,直接从数据库查询最新的订单项:
// 替换原来的foreach部分 // 直接查数据库,拿到最新的所有订单项 $orderItems = OrderItem::where('order_id', $order_id)->get(); $output = ""; foreach ($orderItems as $item) { // 原来的HTML拼接代码完全不变 }
修改后的完整控制器代码
这里用重新加载关联的方法给你贴出完整的修改版:
public function addItem($product_id, Request $request){ $order_id = auth()->user()->waitingOrder->first()->id; $order = Order::find($order_id); $bingo = false; foreach ($order->orderItems as $key => $order_item) { if ($product_id == $order_item->product_id) { $order_item->quantity = $order_item->quantity + 1; $order_item->save(); $bingo = true; break; } } if ($bingo == false) { $new_item = new OrderItem(); $new_item->order_id = $order_id; $new_item->product_id = $product_id; $new_item->save(); // 新增这行,刷新关联缓存 $order->load('orderItems'); } $output = ""; foreach ($order->orderItems as $item) { $output .= '<tr>'. '<td align="left" width="15%">'. '<img style="height: 80px; width: 80px;" src="'. asset('img/products/' . $item->product->image) .'">'. '</td>'. '<td align="center" width="20%">'. $item->product->name . '</td>'. '<td>'. rupiah($item->product->price) . '</td>'. '<td width="14%">'. '<input type="number" class="form-control" name="quantity" value="'. $item->quantity .'" min="1" max="'. $item->product->stock .'">'. '</td>'. '<td>'. rupiah($item->product->price * $item->quantity) . '</td>'. '<td>'. '<a href="'. route('kasir.remove.item', $item->product->id ) .'" class="remove-btn">'. '<span class="icon_close"></span>'. '</a>'. '</td>'. '</tr>'; } return response($output); }
这样修改后,第一次添加新商品时,渲染HTML用的就是数据库里最新的订单项集合了,问题就能解决!
内容的提问来源于stack exchange,提问作者Muh Ghifari
相关产品推荐
相关产品推荐

