queryraw是think\db\expression\queryraw表达式类,用于orm中安全嵌入原生sql片段,配合where、field、order等方法实现函数调用、子查询等,避免sql注入。

ThinkPHP 的 QueryRaw 主要用于在 ORM 查询中安全嵌入原生 SQL 片段,它不是独立类,而是 think\db\expression\QueryRaw 表达式类,配合 where()、field()、order() 等方法使用,避免字符串拼接导致的 SQL 注入。
QueryRaw 在 where 条件中嵌入原生表达式
当需要使用 MySQL 函数、子查询或复杂逻辑判断时,直接写字符串易出错且不安全。QueryRaw 可将原生片段标记为“已信任”,由框架自动处理参数绑定。
- 用法示例:查询创建时间在最近 7 天内的用户
php
use think\db\expression\QueryRaw;
$result = Db::name('user')
->where('create_time', '>=', new QueryRaw('DATE_SUB(NOW(), INTERVAL 7 DAY)'))
->select();
?>
注意:QueryRaw 中的内容不会被转义,但需确保其本身不含用户输入;若含变量,应改用参数绑定(如 ['DATE_SUB(NOW(), INTERVAL ? DAY)', 7])而非拼接。
QueryRaw 配合 field() 返回计算字段
在 field() 中使用 QueryRaw,可添加数据库函数结果作为虚拟字段。
- 示例:查用户并附带年龄(按生日计算)
$result = Db::name('user')
->field('id, name, new QueryRaw("TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age")')
->select();
?>
⚠️ 实际写法需避免字符串内直接写对象 —— 正确方式是数组传参:
$result = Db::name('user')
->field(['id', 'name', new QueryRaw('TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age')])
->select();
?>
QueryRaw 用于 order() 或 having() 场景
排序或分组后筛选常需函数支持,比如按中文拼音首字母排序、按距离排序等。
- 按城市名称拼音首字母分组统计
Db::name('user')
->field('LEFT(CONVERT(city USING gbk), 1) AS first_char, COUNT(*) as total')
->group(new QueryRaw('LEFT(CONVERT(city USING gbk), 1)'))
->order(new QueryRaw('first_char'))
->select();
?>
这里 group() 和 order() 均接受 QueryRaw,确保表达式原样进入 SQL,同时保持链式调用清晰。
替代方案对比:raw() 与 QueryRaw 的区别
ThinkPHP 6+ 中,raw() 是更简洁的助手函数(本质就是 new QueryRaw),推荐日常使用。
-
new QueryRaw('...'):显式、适合复杂场景或 IDE 提示明确 -
raw('...'):需 usethink\facade\Db或think\db\Raw,写法更短
例如:
use think\db\Raw;
// 等价于 new QueryRaw('...')
->where('status', '=', Raw::raw('IFNULL(status, 0)'))
?>
多数情况下,raw('...') 更轻量,但注意不要与模型属性名冲突(如字段名恰好叫 raw)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











