如何在Eloquent的with闭包$query中传递父表_user_id字段值
解决Laravel关联查询中
with闭包内引用父模型字段的问题 我清楚你碰到的麻烦:在hasMany关联场景下,想在with方法的闭包查询里用上父表的_user_id字段值,但不知道怎么传递这个值到闭包中。咱们一步步拆解解决这个问题。
问题核心分析
先看你的关联定义,其实已经通过外键映射把父表的_user_id和关联表的user_id绑定了:
public function response_pricings(){ return $this->hasMany('App\Models\Website\RFXRequestPricingResponse', ['rfx_request_id'=>'_rfx_request_id', 'user_id'=>'_user_id'])->selectRaw("*"); }
但你尝试在with闭包里直接写$query->where('user_id', $_user_id)时,闭包无法直接访问父模型的字段变量。这时候需要用Laravel关联查询的特性来处理父字段的引用。
可行解决方案
方案1:用whereColumn匹配关联字段
如果你的需求是确保关联的response_pricings数据的user_id和当前父模型的_user_id一致,其实这个约束已经在关联定义里自动生效了,不需要额外加where。但如果是要基于父字段做额外过滤,可以这样写:
->with(['response_pricings' => function ($query) { // 直接通过表字段关联,让关联表user_id匹配父表的_user_id $query->whereColumn('user_id', 'rfx_request_suppliers_responded._user_id'); // 这里可以追加其他自定义条件,比如: // $query->where('status', 'active')->whereColumn('user_id', 'rfx_request_suppliers_responded._user_id'); }])
Laravel在关联查询时会自动处理表的关联关系,用表的原始字段名(父表名rfx_request_suppliers_responded+字段_user_id)就能正确匹配每个父模型对应的字段值。
方案2:针对单模型场景传递父值(批量查询不适用)
如果是单个父模型的查询场景,你可以通过use关键字把父模型的字段值引入闭包:
// 假设先获取单个父模型实例 $model = RFXRequestSupplierResponded::where('rfx_request_id', $rfx_request_id)->first(); $model->load(['response_pricings' => function ($query) use ($model) { $query->where('user_id', $model->_user_id); }]);
但注意这种方式只适合单模型,批量查询(比如get()返回集合)时,use的是固定值,无法对应每个父模型的不同_user_id,所以优先用方案1。
代码优化建议
你主查询里用子查询获取user_name和note的写法,其实可以用Laravel的关联查询替代,让代码更简洁易维护:
// 先在RFXRequestSupplierResponded模型里定义关联 public function user() { return $this->belongsTo(User::class, 'user_id'); } public function responseNote() { return $this->hasOne(RFXRequestResponseNote::class, ['rfx_request_id' => '_rfx_request_id', 'user_id' => '_user_id']); } // 然后重构查询代码 return RFXRequestSupplierResponded::select( 'id as _id', 'rfx_request_id as _rfx_request_id', 'user_id as _user_id', 'status', 'is_qualified' ) ->with([ 'user:id,name', // 只加载需要的字段,提升性能 'responseNote:rfx_request_id,user_id,note', 'response_pricings' ]) ->where('rfx_request_id', $rfx_request_id) ->get() ->map(function ($item) { // 把关联字段赋值成需要的别名 $item->user_name = $item->user->name; $item->note = $item->responseNote?->note; return $item; });
这种写法更符合Laravel的优雅风格,也方便后续维护。
内容的提问来源于stack exchange,提问作者dev21
相关产品推荐
相关产品推荐

