Laravel中基于ID数组关联purchases与purchase_types表的实现
问题分析
你的代码返回空数组的核心原因是:purchases表的purchaseCategory字段存储的是JSON格式的ID数组,而你用普通的等值join和whereIn是在拿数组字符串和单个ID数值做匹配,两者不可能相等,因此无法命中任何数据。
解决方案
根据Laravel的特性,我们可以利用JSON查询语法来处理这类数组字段,以下提供两种实现方式:
方式一:使用Query Builder(无模型)
1. 查询符合条件的采购记录
先筛选出purchaseCategory包含指定ID的采购数据:
$purchaseIds = [1, 2]; $purchases = DB::table('purchases') ->where(function ($query) use ($purchaseIds) { // 遍历目标ID,用orWhereJsonContains匹配数组中包含任意目标ID的记录 foreach ($purchaseIds as $id) { $query->orWhereJsonContains('purchaseCategory', $id); } }) ->get();
2. 批量获取对应的采购类型
为了避免N+1查询,先收集所有涉及的类型ID,再一次性查询:
// 提取所有采购记录中的类型ID,去重 $allTypeIds = collect($purchases) ->pluck('purchaseCategory') ->flatten() ->unique(); // 批量查询类型名称,用ID作为键名方便后续匹配 $purchaseTypes = DB::table('purchase_types') ->whereIn('id', $allTypeIds) ->pluck('purchaseType', 'id');
方式二:使用Eloquent模型(推荐)
如果已经定义了模型,我们可以用访问器简化类型名称的获取:
1. 定义模型与访问器
// app/Models/Purchase.php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Purchase extends Model { protected $casts = [ 'purchaseCategory' => 'array', // 自动将JSON字段转为数组 ]; // 定义访问器,直接返回对应的采购类型名称字符串 public function getPurchaseTypeNamesAttribute() { return PurchaseType::whereIn('id', $this->purchaseCategory) ->pluck('purchaseType') ->implode(', '); } }
// app/Models/PurchaseType.php namespace App\Models; use Illuminate\Database\Eloquent\Model; class PurchaseType extends Model { // 模型默认配置即可 }
2. 控制器查询
$purchaseIds = [1, 2]; $purchases = Purchase::where(function ($query) use ($purchaseIds) { foreach ($purchaseIds as $id) { $query->orWhereJsonContains('purchaseCategory', $id); } })->get();
Blade模板显示
对应Query Builder方式的显示
@foreach($purchases as $purchase) <div class="purchase-item"> <h4>采购ID: {{ $purchase->id }}</h4> <p>采购类型: @foreach($purchase->purchaseCategory as $typeId) {{ $purchaseTypes[$typeId] }}@if(!$loop->last), @endif @endforeach </p> </div> @endforeach
对应Eloquent模型方式的显示
直接调用访问器即可,无需额外处理:
@foreach($purchases as $purchase) <div class="purchase-item"> <h4>采购ID: {{ $purchase->id }}</h4> <p>采购类型: {{ $purchase->purchase_type_names }}</p> </div> @endforeach
内容的提问来源于stack exchange,提问作者16_018_RHR
相关产品推荐
相关产品推荐

