Laravel Eloquent关联查询报错:Property [model_b]不存在于Builder实例
问题原因
ModelA::find(1)返回的是单个ModelA模型实例,此时访问model_b是Eloquent的动态关联属性,会自动执行关联查询返回对应的ModelB集合。
而ModelA::where('name','=',$name)返回的是Eloquent查询构建器(Builder)实例,它还未执行查询获取模型实例,所以直接访问model_b属性会报错——构建器对象本身不存在这个属性。
解决方案
根据你的实际需求选择对应方案:
1. 获取单个符合条件的ModelA对应的ModelB集合
如果name字段唯一,或你只需要第一个匹配的ModelA的关联数据,先通过first()获取模型实例,再访问关联:
$lastWeek = ModelA::where('name', '=', $name) ->first() ->model_b; // 无需额外调用get(),动态属性已直接返回关联集合
注意:如果没有匹配的ModelA,
first()会返回null,直接访问model_b会触发报错,建议先做判断:
$modelA = ModelA::where('name', '=', $name)->first(); if ($modelA) { $lastWeek = $modelA->model_b; } else { // 处理无匹配数据的场景 }
2. 获取所有符合条件的ModelA对应的所有ModelB集合
如果要获取所有满足name条件的ModelA关联的全部ModelB数据,有两种高效实现方式:
方式一:预加载关联后提取数据
先预加载model_b关联,再通过集合方法提取所有关联数据:
$modelAs = ModelA::where('name', '=', $name) ->with('model_b') ->get(); $lastWeek = $modelAs->flatMap(function ($modelA) { return $modelA->model_b; });
方式二:从ModelB反向查询(更高效)
先在ModelB中定义与ModelA的反向关联:
class ModelB extends Model { use HasFactory; public function model_a() { return $this->belongsTo(ModelA::class); } }
然后直接从ModelB层面过滤关联的ModelA符合条件的数据:
$lastWeek = ModelB::whereHas('model_a', function ($query) use ($name) { $query->where('name', '=', $name); })->get();
这种方式直接在数据库层面完成过滤,避免加载多余的ModelA数据,性能更优。
内容的提问来源于stack exchange,提问作者Anja Euanthe
相关产品推荐
相关产品推荐

