Laravel中使用whereHas筛选子关联无NULL值记录结果不符合预期的问题
解决Laravel中whereHas筛选所有关联记录均满足条件的问题
我懂你的需求:你想要的是只有当某个Bill_of_Lading关联的所有delivery_order的date_delivered字段都不为NULL时,才返回这条主模型记录。而你之前用的whereHas逻辑刚好相反——它会返回至少有一个关联delivery_order满足date_delivered不为NULL的主模型,这就是为什么你会得到包含NULL值的结果。
正确的解决方案:用whereDoesntHave反转逻辑
要实现“所有关联记录都无NULL值”,等价于“不存在任何一个关联记录的date_delivered为NULL”。我们可以用whereDoesntHave来构建这个查询:
return App\Bill_of_Lading::with('transactions.confirmed_transaction.delivery_order') ->whereDoesntHave('transactions.confirmed_transaction.delivery_order', function ($query) { $query->whereNull('date_delivered'); })->get();
为什么这个方法能解决问题?
whereDoesntHave的作用是筛选出没有符合闭包条件的关联记录的主模型。这里闭包用来查找date_delivered为NULL的delivery_order,所以最终返回的就是那些所有关联delivery_order的date_delivered都不为NULL的Bill_of_Lading。- 如果你同时需要加载关联数据,并且希望加载的关联也只包含非NULL的记录,可以在
with里加上约束:
return App\Bill_of_Lading::with(['transactions.confirmed_transaction.delivery_order' => function($query) { $query->whereNotNull('date_delivered'); }]) ->whereDoesntHave('transactions.confirmed_transaction.delivery_order', function ($query) { $query->whereNull('date_delivered'); })->get();
再说说你之前的尝试为什么不对
- 第一次使用
whereHas:它的逻辑是“只要有一个关联记录满足条件就返回主模型”,所以哪怕10个关联里9个是NULL,只要有1个不是,这条主模型就会被返回,完全不符合你的需求。 - 用
with加关联约束:这只会过滤加载的关联数据,不会影响主模型的查询结果——主模型还是会全部返回,只是关联数据里只显示符合条件的部分,所以你依然会看到带NULL的主模型。 - 嵌套where闭包:这和第一次的
whereHas逻辑完全一致,只是多套了一层结构,没有改变本质问题。
内容的提问来源于stack exchange,提问作者the_emotional_21
相关产品推荐
相关产品推荐

