最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在Laravel 11中如何安全地编写原始SQL查询语句?
时间:2026-07-02 11:17:02 编辑:袖梨 来源:一聚教程网
DB::select()专用于SELECT查询,返回stdClass对象数组并自动预处理防注入;其他操作应使用对应专用方法,禁用DB::raw()执行SQL,注意占位符、类型安全与事务显式管理。
直接用 DB::select()、DB::insert()、DB::update()、DB::delete() 四个方法,别碰 DB::raw() 执行语句——它根本不执行,只是个标记。
SELECT 查询必须用 DB::select()
这个方法专为 SELECT 设计,返回 stdClass 对象数组,自动启用 PDO 预处理,天然防注入。传错类型(比如塞 INSERT)不会报错,但结果为空,MySQL 非严格模式下尤其难发现。
- 只支持
?占位符或命名绑定(如:name),但命名绑定需显式传 PDO 选项:DB::select('SELECT * FROM users WHERE name = :name', ['name' => 'Alice'], [PDO::ATTR_EMULATE_PREPARES => true]) -
IN子句不能写成WHERE id IN (?)——PDO 不支持数组绑定,得手动拼占位符:DB::select("SELECT * FROM users WHERE id IN (" . implode(',', array_fill(0, count($ids), '?')) . ")", $ids) - 日期建议先用
Carbon::parse($date)->toDateTimeString()格式化,避免时区差异导致漏查 - 返回值全是字符串(
TINYINT(1)字段返回"1"而非布尔值),不走模型生命周期,$casts、访问器全失效
写操作别用 DB::statement() 替代专用方法
DB::insert()、DB::update()、DB::delete() 返回明确语义(影响行数或布尔值),强制参数绑定,比 DB::statement() 更安全可控。
-
DB::insert()不返回自增 ID;要取 ID 得改用DB::table()->insertGetId()或DB::getPdo()->lastInsertId() -
DB::update()和DB::delete()的WHERE条件务必先验证——漏条件或类型不匹配可能误改/删全表 - 批量插入别循环调
DB::insert();应拼成单条INSERT INTO ... VALUES (),(),()再用DB::statement() -
DB::statement()底层是PDO::exec(),不返回数据集,写SELECT 1会直接报错
DB::raw() 只能嵌入构建器,不是执行入口
它本质是告诉查询构建器“这段字符串我信,别转义”,本身不执行任何 SQL。常见误用:把整条 SQL 包进 DB::raw() 然后试图运行——只会生成一个无意义的 Raw 实例,毫无效果。
- 正确用法是在
select()、whereRaw()、orderByRaw()中嵌入片段,例如:User::select('id', DB::raw('DATE_FORMAT(created_at, "%Y-%m") as month'))->get() -
whereRaw()仍需手动传参数数组:->whereRaw('created_at > DATE_SUB(NOW(), INTERVAL ? DAY)', [7]) - 别在
whereRaw()里拼用户输入:->whereRaw("name = '{$name}'")是严重注入漏洞 - 字段别名必须显式写出:
DB::raw('COUNT(*) as total'),否则结果里找不到total
最易被忽略的是:所有原生查询都不自动参与 Eloquent 的延迟加载、批量优化或模型事件;事务需显式用 DB::transaction() 包裹,混用 DB::select() 和 DB::statement() 还可能因未消费结果集导致后续查询失败。
相关文章
- B站有奖解谜活动首期答案 07-02
- 潜水员戴夫如何获取黄玉 07-02
- REPLACED第九章全部收集品位置一览 07-02
- 轻漫岛app目录如何调正序 07-02
- 功夫熊猫神龙大侠新服何时开启 07-02
- 白银之城尔阁酒保 白银之城尔阁酒保角色背景与剧情解析 07-02