如何用Laravel Eloquent查询含真值的列及相关技术疑问
问题背景
我有一个Post模型,对应的is_verified列数据类型为smallint。原本使用以下Eloquent代码查询所有已验证的记录:
Post::where('is_verified', true)->get();
这段代码生成的SQL语句如下:
select * from `posts` where `posts`.`is_verified` = true
当is_verified的值为0或1时,该查询能正常获取已验证的Post记录;但当我手动将部分记录的is_verified值改为2这类非1的“真值”后,上述Eloquent查询无法获取到这些记录。直接执行该SQL语句也存在同样问题,而将SQL中的=改为is后,查询可正常获取所有含真值的记录:
select * from `posts` where `posts`.`is_verified` is true
我的疑问:
- 上述行为是否符合预期?
- 如何用Eloquent执行上述使用
is true的SQL查询?我想到的方式是where('is_verified', '!=', 0),但在复杂长查询中可读性较差。 is_verified列的smallint类型是否会影响该行为?因为相关讨论提到布尔列通常为tinyint而非smallint。
回答
1. 该行为完全符合预期
在SQL语法中,=属于等值比较运算符,当你写= true时,数据库会将true转换为对应的数值(多数数据库中是1),所以is_verified = true本质上等价于is_verified = 1,自然匹配不到值为2的记录。而is true是布尔逻辑判断,数据库会将所有非0的数值判定为真,因此能匹配所有非0的is_verified值。
2. 用Eloquent实现is true查询的几种方案
- 直接使用
whereRaw写入原生SQL条件:
这种方式最直接,完全还原你需要的SQL逻辑,可读性较强。Post::whereRaw('is_verified is true')->get(); - 自定义查询作用域(推荐复杂查询场景):
在Post模型中定义一个查询作用域:
后续查询时直接调用该作用域即可,复杂查询中会让代码更简洁易读:public function scopeVerified($query) { return $query->whereRaw('is_verified is true'); }Post::verified()->get(); - 结合
DB::raw使用where方法:
借助DB::raw构造表达式,也能实现需求:use Illuminate\Support\Facades\DB; Post::where(DB::raw('is_verified'), 'is', true)->get();
3. smallint类型不影响核心行为
不管是tinyint还是smallint,只要是整数类型,数据库对= true和is true的处理逻辑是一致的:= true会转为等值匹配1,is true会判断非0值为真。两者的区别仅在于存储空间——tinyint占用空间更小,更适合存储布尔值(毕竟布尔只需要0/1两种状态),但这和你遇到的查询行为没有直接关联。
内容的提问来源于stack exchange,提问作者rifqy abdl
相关产品推荐
相关产品推荐

