db::raw() 是 tp8 中唯一安全可用的表达式更新方式,原 tp5 的 ['exp', 'xxx'] 写法已彻底废弃,必须替换为 db::raw('xxx'),否则将导致 sql 异常或静默写错数据。

Db::raw() 是唯一安全可用的表达式更新方式,TP5 的 ['exp', 'xxx'] 写法在 TP8 中已彻底废弃,硬套会触发 SQL 解析异常或静默失败。
TP5 的 ['exp', 'login_times+1'] 在 TP8 里直接报错
TP5 允许在 update 数组中用 ['exp', 'xxx'] 表示原生表达式,但 TP8 的查询构建器已重构,该语法不再被识别——它既不会转义,也不会执行,多数情况抛出 InvalidArgumentException 或生成非法 SQL。你看到的“没报错但没生效”,大概率是字段被当成字符串字面量写入(比如把 'login_times+1' 当成普通字符串存进数据库)。
- 必须全部替换为
Db::raw('login_times + 1') -
Db::raw()返回的是 Raw 对象,会被构建器原样插入 SQL,不加引号、不转义 - 多个表达式可混用:
['score' => Db::raw('score + ?'), 'updated_at' => Db::raw('now()')],其中?仍支持参数绑定
setInc()/setDec() 在 TP8 中行为不变但需注意主键条件
这两个快捷方法在 TP8 里保留,语义和返回值一致(返回影响行数),但底层已切换为 Db::raw() 实现。问题常出在条件缺失:
- 调用前必须确保已链式指定 where,例如
Db::table('user')->where('id', 1)->setInc('score') - 若漏掉
where(),TP8 默认不会拦截,可能全表自增——这比 TP5 更危险 - TP8 严格校验字段存在性,
setInc('non_exists_field')直接抛异常,TP5 可能静默忽略
链式 inc()/dec()/exp() 方法已移除
TP5.0.5+ 推广的链式写法如 ->inc('read')->exp('name', 'UPPER(name)')->update(),在 TP8 中已被完全删除。源码里找不到对应方法,调用即报 Call to undefined method。
- 替代方案只有两种:
Db::raw()显式构造,或改用模型save()+Db::raw() - 不要尝试封装兼容层去“恢复”这些链式方法——TP8 查询构建器的解析逻辑已不可逆变更
- 如果你依赖这类链式风格,建议统一收口到一个工具函数,内部用
Db::raw()拼装字段
Db::raw() 不再是可选项,而是唯一合法出口。漏掉它,哪怕只有一处 ['exp', ...],升级后就可能在线上静默写错数据。











