Laravel 10:如何编写带动态where条件的HasOne关联?
动态筛选HasOne关联中的owner_model_id
针对你的需求,有几种实用的方案可以实现动态筛选extra_field_values表中的owner_model_id:
方案1:Eager Loading时通过闭包动态添加约束
无需修改原关联方法,在调用with()时传入闭包,直接给关联查询注入动态条件:
// 动态获取owner_model_id,比如从请求、当前用户等渠道 $targetOwnerId = request()->input('owner_model_id'); $extraFields = ExtraField::with(['fieldValue' => function ($query) use ($targetOwnerId) { $query->where('owner_model_id', $targetOwnerId); }])->get();
原关联的withDefault逻辑会正常生效,当无匹配记录时返回预设的默认值。
方案2:定义带参数的专用关联方法
在ExtraField模型中新增一个接受owner_model_id参数的关联方法,封装筛选逻辑:
/** * @param int $ownerModelId * @return \Illuminate\Database\Eloquent\Relations\HasOne */ public function fieldValueForOwner(int $ownerModelId): HasOne { return $this->hasOne(ExtraFieldValue::class, 'extra_field_id') ->where('owner_model_id', $ownerModelId) ->withDefault([ 'value' => null, ]); }
使用时直接调用该方法并传入参数:
$extraFields = ExtraField::with(['fieldValueForOwner' => fn($query) => $query->where('owner_model_id', 4)])->get(); // 或者更简洁的写法(Laravel 8+支持) $extraFields = ExtraField::with('fieldValueForOwner:4')->get();
方案3:利用模型临时属性传递上下文值
如果当前业务场景中有固定的上下文owner_model_id(如当前登录用户的关联ID),可以通过模型属性传递:
- 在
ExtraField模型中添加属性和 setter 方法:
protected ?int $ownerModelId = null; public function setOwnerModelId(int $id): self { $this->ownerModelId = $id; return $this; }
- 修改原关联方法,判断并添加约束:
public function fieldValue(): HasOne { $query = $this->hasOne(ExtraFieldValue::class, 'extra_field_id') ->withDefault([ 'value' => null, ]); if ($this->ownerModelId !== null) { $query->where('owner_model_id', $this->ownerModelId); } return $query; }
- 使用时先设置属性再执行查询:
$extraFields = (new ExtraField())->setOwnerModelId(3)->with('fieldValue')->get();
内容的提问来源于stack exchange,提问作者Matt Komarnicki
相关产品推荐
相关产品推荐

