从多表获取数据导致视图数据重复的问题解决求助
解决订单与订单项数据展示重复问题
问题描述
尝试从order和order_item两张表展示数据,当前代码如下:
Controller 代码
public function index() { $order = DB::table('order')->get(); $order_item = DB::table('order_item')->get(); return view('admin.orders', compact('order','order_item')); }
View 代码
@foreach ($order as $orders) @foreach ($order_item as $order_items) <tr> <th style="padding: 20px">{{ $orders->id }}</th> <th style="padding: 20px">{{ $order_items->order_id }}</th> <th style="padding: 20px"> <a><i style="color: #6565D8" class="fa-solid fa-location-dot"></i></a> <a><i style="color: #6565D8" class="fa-solid fa-eye"></i></a> <a><i style="color: #6565D8" class="fa-solid fa-eye"></i></a> </th> </tr> @endforeach @endforeach
目前问题:$orders->id重复显示,次数等于order_item表的总行数,而$order_items->order_id无重复。
问题原因
两层嵌套循环导致每个订单都会遍历所有订单项,所以每个订单ID会重复输出,次数对应订单项的总数。
解决方案
方案1:使用数据库JOIN查询
直接在Controller中通过JOIN关联两张表,获取关联后的数据集,避免嵌套循环:
public function index() { // 关联order和order_item表,查询关联数据 $ordersWithItems = DB::table('order') ->join('order_item', 'order.id', '=', 'order_item.order_id') ->select('order.id as order_id', 'order_item.*') // 按需选择需要的字段 ->get(); return view('admin.orders', compact('ordersWithItems')); }
View中只需一层循环:
@foreach ($ordersWithItems as $item) <tr> <th style="padding: 20px">{{ $item->order_id }}</th> <th style="padding: 20px">{{ $item->order_id }}</th> <!-- 如果需要显示订单项的其他字段,比如商品ID:{{ $item->product_id }} --> <th style="padding: 20px"> <a><i style="color: #6565D8" class="fa-solid fa-location-dot"></i></a> <a><i style="color: #6565D8" class="fa-solid fa-eye"></i></a> <a><i style="color: #6565D8" class="fa-solid fa-eye"></i></a> </th> </tr> @endforeach
方案2:使用Eloquent模型关联(推荐)
如果项目使用Eloquent ORM,先定义模型关联:
Order模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Order extends Model { protected $table = 'order'; // 指定表名 // 定义与订单项的一对多关联 public function items() { return $this->hasMany(OrderItem::class, 'order_id'); } }
OrderItem模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; class OrderItem extends Model { protected $table = 'order_item'; // 指定表名 }
然后在Controller中预加载关联数据:
public function index() { // 预加载订单项,避免N+1查询问题 $orders = Order::with('items')->get(); return view('admin.orders', compact('orders')); }
View中按关联关系循环:
@foreach ($orders as $order) <!-- 遍历当前订单的所有订单项 --> @foreach ($order->items as $item) <tr> <th style="padding: 20px">{{ $order->id }}</th> <th style="padding: 20px">{{ $item->order_id }}</th> <th style="padding: 20px"> <a><i style="color: #6565D8" class="fa-solid fa-location-dot"></i></a> <a><i style="color: #6565D8" class="fa-solid fa-eye"></i></a> <a><i style="color: #6565D8" class="fa-solid fa-eye"></i></a> </th> </tr> @endforeach @endforeach
两种方案对比
- JOIN查询:适合只需要简单关联数据的场景,执行效率高。
- Eloquent关联:更符合Laravel的ORM设计,便于后续扩展业务逻辑,还能避免N+1查询问题。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

