如何在Eloquent查询内获取当前模型ID作为with关联条件
Eloquent预加载中获取当前模型ID的方案
核心认知纠正
你不需要手动在预加载闭包里获取当前商品ID传参做外键匹配:Eloquent的关联预加载逻辑会自动根据模型中定义的关联外键规则匹配对应数据,你代码里写的where('product_id', $idOfModel)属于重复逻辑,只要关联定义正确,这段条件完全不需要手动添加。
另外你当前的with传参写法有误:如果要给关联添加查询约束,需要用「关联名 => 闭包函数」的数组格式传参,不能把闭包作为with的第二个参数传入。
为什么在with闭包里拿不到当前模型ID
with预加载是批量查询逻辑:它会先查出主表(商品表)的10条结果,收集所有主模型ID,再通过whereIn一次性查出所有关联数据,最后在内存中完成数据匹配,整个过程不会逐模型遍历执行闭包,所以闭包里不存在单个「当前模型」的上下文,自然拿不到对应的$idOfModel。
必须手动获取当前模型ID的实现方案
如果你的业务有特殊逻辑,必须拿到每个商品的ID做自定义查询约束,可以改用延迟预加载,在拿到主模型集合后遍历逐个加载关联,这时候可以直接拿到每个商品实例的ID:
// 先查主模型和第一层关联 $products = Product::with('attributes')->take(10)->get(); // 遍历逐个加载嵌套关联,此时可以直接拿到当前商品的ID $products->each(function ($product) { $product->load([ 'attributes.product_options' => function ($q) use ($product) { $q->where('product_id', $product->id) ->with(['variable' => function ($q) use ($product) { $q->where('product_id', $product->id); }]); } ]); });
注意:该方案会产生N+1查询问题,性能远低于默认的批量预加载,仅适合特殊定制场景使用。
常规场景最优写法
如果只是做关联数据加载,不需要额外的特殊条件判断,直接用嵌套预加载语法即可,Eloquent会自动完成外键匹配,你只需要在闭包里写额外的查询规则(比如分组、排序、字段筛选):
$products = Product::with([ 'attributes.product_options.variable' ])->take(10)->get(); // 如果要给中间关联加分组等约束,可以按层级写闭包 $products = Product::with([ 'attributes' => function ($q) { $q->with([ 'product_options' => function ($q) { $q->groupBy('id')->with('variable'); } ]); } ])->take(10)->get();
如果你的关联需要固定加product_id过滤条件,建议直接在模型的关联定义方法里添加约束,而不是在每次预加载的时候手动写where条件,一次定义全局生效。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

