You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Laravel中selectRaw与DB::select(DB::raw())的区别及SQL注入疑问

Laravel中DB::table()->selectRaw()与DB::select(DB::raw())的区别及SQL注入风险解析

咱们先拆解这两段Laravel查询代码的核心区别,再聊聊你关心的SQL注入风险问题:

一、两段代码的核心差异

1. 执行机制与返回结果类型

  • 第一段代码是基于Laravel查询构建器(Query Builder)的链式调用:

    DB::table('some_table')->selectRaw('COUNT(*) AS result')->get();
    

    它借助查询构建器封装的逻辑生成最终SQL,返回的是Illuminate\Support\Collection集合对象,集合里的元素是Laravel封装的stdClass实例,你可以通过$collection->first()->result这种更Laravel风格的方式获取结果。

  • 第二段代码是直接执行原生SQL:

    DB::select(DB::raw("SELECT COUNT(*) AS result FROM some_table"));
    

    它跳过了查询构建器的部分封装,直接传入原生SQL语句执行,返回的是PHP原生数组,数组元素同样是stdClass实例,取值方式类似,但缺失了查询构建器带来的集合操作便利性。

2. 扩展性与灵活性

  • 第一段的查询构建器方式支持链式扩展,比如后续要加筛选条件、分组、排序等,直接追加链式方法即可:
    DB::table('some_table')
      ->selectRaw('category, COUNT(*) AS count')
      ->where('status', 1)
      ->groupBy('category')
      ->get();
    
  • 第二段的原生SQL方式如果要修改查询逻辑,只能直接修改SQL字符串本身,复杂场景下维护成本高,灵活性差很多。

二、SQL注入风险问题

首先明确结论:selectRaw和DB::raw()本身都存在SQL注入风险,风险的根源不是方法本身,而是你是否直接将未过滤的用户输入拼接到了原生SQL字符串中

Laravel文档提到的raw()风险,指的是这种危险用法:

// 高危!直接拼接用户输入,存在SQL注入
$userInput = request('category');
DB::table('some_table')->selectRaw("COUNT(*) AS result WHERE category = $userInput")->get();

但只要你采用参数绑定的方式传递动态内容,不管是selectRaw还是DB::raw()都是安全的:

  • 安全的selectRaw用法(两种方式):
    // 方式1:配合查询构建器的where方法绑定参数
    $userInput = request('category');
    DB::table('some_table')
      ->selectRaw('COUNT(*) AS result')
      ->where('category', $userInput)
      ->get();
    
    // 方式2:直接在selectRaw中绑定参数
    DB::table('some_table')
      ->selectRaw('COUNT(*) AS result WHERE category = ?', [$userInput])
      ->get();
    
  • 安全的DB::raw()用法:
    $userInput = request('category');
    DB::select(DB::raw("SELECT COUNT(*) AS result FROM some_table WHERE category = ?"), [$userInput]);
    

总结一下:这两个方法本身没有安全等级的差异,只要你避免直接拼接用户可控的输入到SQL字符串中,而是用参数绑定的方式传递动态值,就能有效避免SQL注入风险。

内容的提问来源于stack exchange,提问作者pmiranda

火山引擎 最新活动