在Laravel的Eloquent ORM中,关联查询是处理模型间关系数据的常用操作,不存在性关联查询指的是筛选出主模型没有对应关联记录的数据,这类需求在业务中非常常见,比如查询没有发布过文章的用户、没有未完成订单的客户等。
核心方法:whereDoesntHave
Laravel提供了whereDoesntHave方法专门用于处理不存在性关联查询,它的作用和whereHas相反,whereHas是筛选存在对应关联记录的模型,而whereDoesntHave是筛选不存在对应关联记录的模型。
基础使用语法
方法的基本调用格式如下:
<?php
// 假设User模型关联了Post模型,关联方法名为posts
$users = User::whereDoesntHave('posts')->get();
// 上述代码会查询所有没有发布过文章的用户
?>
带条件的关联不存在查询
如果需要在判断关联不存在的同时,附加关联模型的筛选条件,可以给whereDoesntHave传入第二个闭包参数,闭包中定义关联模型的查询条件:
<?php
// 查询没有发布过状态为已审核文章的用户
$users = User::whereDoesntHave('posts', function ($query) {
$query->where('status', 'approved');
})->get();
?>
多关联嵌套的不存在查询
当存在多层关联关系时,比如User关联Post,Post关联Comment,需要查询没有关联评论的文章对应的用户,可以使用嵌套的whereDoesntHave:
<?php
// 查询没有发布过带评论的文章的用户
$users = User::whereDoesntHave('posts.comments')->get();
?>
与whereHas的对比
为了更清晰理解whereDoesntHave的作用,我们可以对比它和whereHas的差异:
| 方法名 | 作用 | 示例场景 |
|---|---|---|
| whereHas | 筛选存在对应关联记录的模型 | 查询发布过文章的用户 |
| whereDoesntHave | 筛选不存在对应关联记录的模型 | 查询没有发布过文章的用户 |
注意事项
- 调用
whereDoesntHave时,第一个参数必须是模型中已经定义好的关联方法名称,否则会抛出方法不存在的异常。 - 闭包中的查询条件是对关联模型的筛选,只有满足闭包条件的关联记录都不存在时,主模型才会被筛选出来。
- 如果需要同时处理存在和不存在的关联查询,可以链式调用
whereHas和whereDoesntHave,比如查询发布过文章但没有发布过草稿的用户。
实际业务示例
假设我们有一个订单系统,User模型关联Order模型,Order模型有status字段,值为pending表示未完成,completed表示已完成,现在需要查询所有没有未完成订单的用户:
<?php
// 用户模型关联方法
// User模型中定义
public function orders()
{
return $this->hasMany(Order::class);
}
// 查询逻辑
$usersWithoutPendingOrders = User::whereDoesntHave('orders', function ($query) {
$query->where('status', 'pending');
})->get();
?>
通过上述方法,我们可以快速实现各类不存在性关联查询需求,减少手动编写复杂SQL语句的工作量,同时保证代码的可读性和可维护性。
Laravel关联查询不存在性查询whereDoesntHave修改时间:2026-06-27 23:15:32