Laravel中使用with()子查询时如何关联主表字段筛选?
你遇到的问题是在Laravel嵌套预加载时,无法用主表group_products的id字段作为子查询的筛选条件——直接写'group_products.id'会被当成字符串值,而非字段引用,同时预加载的独立查询也没有关联主表,导致条件失效。
方案一:预加载时用whereExists关联主表字段
通过子查询关联主表与嵌套的order_items表,确保筛选出与当前group_product匹配的订单项:
use Illuminate\Support\Facades\DB; $groups = GroupProduct::where('status', 1) ->with(['groupProductProduct.product' => function ($query) use ($id) { $query->where('products.situation', 1) ->with(['items.orderitems' => function($query2) use ($id) { $query2->where('order_items.order_id', $id) ->whereExists(function ($subQuery) { // 通过中间关联表将order_items与当前group_product关联 $subQuery->select(DB::raw(1)) ->from('group_products_products') ->join('products', 'products.id', '=', 'group_products_products.product_id') ->join('items', 'items.product_id', '=', 'products.id') ->whereColumn('items.id', 'order_items.item_id') ->whereColumn('group_products_products.group_product_id', 'group_products.id'); }) ->with('subitems'); }]); }]) ->get();
方案二:使用join直接关联所有表(更直观)
通过join将所有关联表串联,直接在查询中比较字段,确保筛选逻辑生效,同时预加载所需关联数据:
$groups = GroupProduct::select('group_products.*') ->where('group_products.status', 1) // 关联所有层级的表 ->join('group_products_products', 'group_products_products.group_product_id', '=', 'group_products.id') ->join('products', 'products.id', '=', 'group_products_products.product_id') ->join('items', 'items.product_id', '=', 'products.id') ->join('order_items', 'order_items.item_id', '=', 'items.id') // 添加筛选条件 ->where('products.situation', 1) ->where('order_items.order_id', $id) ->whereColumn('order_items.group_product_id', '=', 'group_products.id') // 预加载完整关联链 ->with(['groupProductProduct.product.items.orderitems.subitems']) // 去重避免重复的group_product记录 ->distinct() ->get();
关键说明
- 当需要比较两个数据库字段而非字段与固定值时,必须用
whereColumn替代where,否则Laravel会把字段名当作字符串值处理。 - 嵌套预加载的查询是独立执行的,无法直接访问主表字段,必须通过子查询(
whereExists)或join的方式建立关联。
内容的提问来源于stack exchange,提问作者gobs
相关产品推荐
相关产品推荐

