PHP Laravel:如何通过关联关系的groupBy处理重复数据
处理重复ID数据的分组合并问题
现有数据表
1. Transaction表
| id | name | date |
|---|---|---|
| 1 | 早间交易 | 2022-09-29 |
| 2 | 晚间交易 | 2022-09-29 |
| 3 | 夜间交易 | 2022-09-29 |
2. Detail Transaction表
| id | transaction_id | item_id | grade |
|---|---|---|---|
| 1 | 1 | 1 | A |
| 2 | 1 | 2 | A |
| 3 | 1 | 1 | B |
| 4 | 1 | 2 | C |
| 5 | 2 | 3 | A |
| 6 | 2 | 3 | B |
| 7 | 3 | 3 | c |
3. Item表
| id | name |
|---|---|
| 1 | XXX |
| 2 | YYY |
| 3 | ZZZ |
模型关联代码
Transaction模型与Detail模型的关联:
class Transaction extends Model { use HasFactory, SoftDeletes; protected $table = 'transactions'; protected $fillable = [ 'name', 'date', ]; public function detail() { return $this->hasMany(Detail::class, 'transaction_id'); } }
当前视图代码及问题
当前尝试通过groupBy分组展示商品名称的视图代码:
<tbody> @forelse ($transction as $data) <tr> <td>{{$data->name}}</td> <td>{{$data->date</td> <td> @foreach($data->detail->groupBy('item_id') as $list) - {{$list->item->name}} @endforeach </td> </tr> @empty <tr> <td>Data Not Found</td> </tr> @endforelse </tbody>
存在的问题:
- 变量名拼写错误:
$transction→$transactions - 语法错误:
{{$data->date缺少闭合括号 - groupBy后
$list是Detail模型的集合,无法直接通过$list->item获取关联模型,需从集合元素中读取 - 未预加载关联,存在N+1查询问题
期望效果
| 交易名称 | 日期 | 明细 |
|---|---|---|
| 早间交易 | 2022-09-29 | -XXX -YYY |
| 晚间交易 | 2022-09-29 | -ZZZ |
| 夜间交易 | 2022-09-29 | -ZZZ |
解决方案
1. 给Detail模型添加Item关联
class Detail extends Model { use HasFactory, SoftDeletes; protected $table = 'detail_transactions'; protected $fillable = ['transaction_id', 'item_id', 'grade']; public function item() { return $this->belongsTo(Item::class); } }
2. 控制器中预加载关联
// 控制器查询代码,预加载detail和对应的item,避免N+1查询 $transactions = Transaction::with('detail.item')->get();
3. 修改视图代码
<tbody> @forelse ($transactions as $data) <tr> <td>{{ $data->name }}</td> <td>{{ $data->date }}</td> <td> {{ '-' . $data->detail->unique('item_id')->pluck('item.name')->implode(' -') }} </td> </tr> @empty <tr> <td colspan="3">Data Not Found</td> </tr> @endforelse </tbody>
代码说明
unique('item_id'):直接过滤掉重复的商品ID,比groupBy更简洁pluck('item.name'):提取所有去重后的商品名称implode(' -'):将名称拼接成-XXX -YYY的格式- 预加载
detail.item避免了循环中重复查询数据库的性能问题 - 修正了原视图中的拼写和语法错误
内容的提问来源于stack exchange,提问作者Toni Rhubanaga
相关产品推荐
相关产品推荐

