应使用 wherenull() 和 wherenotnull() 进行空值查询,它们正确生成 is null/is not null 语句并自动转义字段名;查空字符串或 null 需用闭包组合条件;注意索引支持、软删除机制及业务语义差异。

whereNull() 和 whereNotNull() 是最直接的空值查询方式
查数据库里某个字段为 NULL,别写 where('field', '=', null) —— 这在 Eloquent 里不会生成 IS NULL,而是变成 = ? 绑定参数,结果永远查不到。正确做法是用 Eloquent 内置的 whereNull() 和 whereNotNull()。
它们会准确翻译成 SQL 的 IS NULL 和 IS NOT NULL,且自动处理字段名转义,不拼错、不引号乱套。
-
User::whereNull('email')->get()→ 查所有没填邮箱的用户 -
Post::whereNotNull('published_at')->orderBy('published_at', 'desc')->get()→ 查已发布的文章,按发布时间倒序 - 支持链式调用,和
where()、orderBy()等完全兼容
想查空字符串或 NULL 一起?得手动组合条件
Eloquent 没有内置的 “空字符串或 NULL” 查询方法,因为语义不同:数据库里 '' 是非空字符串,NULL 是缺失值。如果业务上认为两者都算“没数据”,就得显式合并。
常见错误是写成 where('field', '', 'OR WHERE field IS NULL') —— 这语法非法,Eloquent 不认字符串形式的 OR 条件。
- 正确写法用闭包构建 or 查询:
User::where(function ($q) { $q->whereNull('phone')->orWhere('phone', ''); })->get() - 注意括号层级:外层
where()包住整个闭包,否则 OR 会和前面条件变成 AND - 如果字段类型是 JSON 或 TEXT,还要考虑前后空格,可加
trim()在数据库层处理(如 MySQL 用TRIM(field) = ''),但 Eloquent 不直接支持,需用whereRaw()
whereNull() 对索引和性能的影响不能忽略
MySQL 中,IS NULL 查询能否走索引,取决于字段是否允许为 NULL 和索引类型。如果字段定义为 NOT NULL,whereNull() 永远返回空结果,但 Eloquent 不报错,容易误判逻辑。
- 先确认表结构:
DESCRIBE users;看email列的Null列是否为YES - 联合索引中,只有当
NULL字段位于索引最左前缀时,whereNull()才可能命中索引;若在中间或末尾,大概率全表扫描 - PostgreSQL 对
IS NULL的索引支持更好,但需显式创建包含NULLS的索引,例如:CREATE INDEX idx_user_email_null ON users (email) WHERE email IS NULL;
软删除模型里,deleted_at IS NULL 是默认行为,别重复写
用了 SoftDeletes trait 的模型(比如 User),默认查询会自动加上 whereNull('deleted_at')。这时候再手动写 whereNull('deleted_at') 不但冗余,还可能干扰作用域或全局作用域逻辑。
- 要查包括已软删除的数据?用
withTrashed(),不是whereNull('deleted_at') - 只查已删除的?用
onlyTrashed(),它底层就是whereNotNull('deleted_at') - 如果在自定义作用域里误加了
whereNull('deleted_at'),会导致withTrashed()失效 —— 因为两个条件冲突(一个要求为 NULL,一个取消该限制)
'' 和 NULL 当成一回事时,必须明确区分数据库层面的含义,而不是靠 PHP 层补判断。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











