在Laravel的Eloquent ORM中,Raw Expressions原生表达式允许开发者直接在查询中嵌入数据库原生的SQL片段,当需要调用数据库内置函数或者编写复杂SQL逻辑时,这个功能非常实用。使用原生表达式时需要注意避免SQL注入,同时要保证语法符合对应数据库的要求。

什么是Eloquent Raw Expressions
Eloquent Raw Expressions是Laravel提供的一种机制,用于在查询构建器或者Eloquent模型中插入未经ORM处理的原生SQL片段。它不会自动对内容进行转义,因此适合用来调用数据库原生函数或者编写ORM无法直接生成的复杂SQL逻辑。Laravel提供了多种方式来创建Raw Expressions,最常用的是DB::raw()方法。
基础使用方式
最简单的原生表达式使用方式是通过DB::raw()方法包裹原生SQL片段,然后将其用在查询的各个子句中。下面是一个基础的查询示例,调用MySQL的NOW()函数获取当前时间:
<?php
use IlluminateSupportFacadesDB;
use AppModelsUser;
// 查询所有用户,同时获取当前时间作为额外字段
$users = User::select([
'*',
DB::raw('NOW() as current_time')
])->get();
// 输出结果中的当前时间
foreach ($users as $user) {
echo $user->current_time;
}
常见数据库函数调用示例
字符串函数调用
当需要调用数据库的字符串处理函数时,可以使用原生表达式实现。比如MySQL的CONCAT函数拼接两个字段:
<?php
use IlluminateSupportFacadesDB;
use AppModelsUser;
// 拼接用户的姓和名作为全名字段
$users = User::select([
'id',
DB::raw('CONCAT(first_name, " ", last_name) as full_name')
])->get();
foreach ($users as $user) {
echo "用户ID:{$user->id},全名:{$user->full_name}<br/>";
}
日期函数调用
处理日期相关的查询时,经常需要调用数据库的日期函数。比如查询创建时间在最近7天的用户:
<?php
use IlluminateSupportFacadesDB;
use AppModelsUser;
// 查询最近7天创建的用户
$recentUsers = User::where(DB::raw('DATE(created_at)'), '>=', DB::raw('DATE_SUB(CURDATE(), INTERVAL 7 DAY)'))
->get();
echo "最近7天创建的用户数量:" . $recentUsers->count();
聚合函数调用
虽然Eloquent提供了count()、sum()等聚合方法,但复杂场景下还是需要原生表达式。比如同时计算多个聚合值:
<?php
use IlluminateSupportFacadesDB;
use AppModelsOrder;
// 同时计算订单的总金额、平均金额、最大金额
$stats = Order::select([
DB::raw('SUM(amount) as total_amount'),
DB::raw('AVG(amount) as avg_amount'),
DB::raw('MAX(amount) as max_amount')
])->first();
echo "订单总金额:{$stats->total_amount},平均金额:{$stats->avg_amount},最大金额:{$stats->max_amount}";
参数绑定避免SQL注入
直接在DB::raw()中拼接用户输入的内容会有SQL注入风险,这时候需要使用参数绑定。Laravel的原生表达式支持通过第二个参数传入绑定值:
<?php
use IlluminateSupportFacadesDB;
use AppModelsUser;
// 安全的参数绑定示例,避免SQL注入
$searchName = "张";
$users = User::where(DB::raw('first_name LIKE ?', ["%{$searchName}%"]))
->get();
// 也可以使用select子句中的参数绑定
$users = User::select([
'id',
DB::raw('CONCAT(first_name, ?, last_name) as full_name', [" "])
])->get();
不同场景下的使用位置
原生表达式可以用在查询的多个位置,常见的使用场景如下:
- select子句:用于添加原生SQL计算的字段,如上面的函数调用示例
- where子句:用于编写复杂的查询条件,比如调用日期函数过滤数据
- order by子句:用于按照原生函数计算的结果排序
- group by子句:用于对原生表达式计算的结果分组
下面是一个按照原生表达式计算结果排序的示例:
<?php
use IlluminateSupportFacadesDB;
use AppModelsProduct;
// 按照商品名称的长度排序
$products = Product::orderBy(DB::raw('LENGTH(name)'))
->get();
foreach ($products as $product) {
echo "商品名:{$product->name},名称长度:" . strlen($product->name) . "<br/>";
}
使用注意事项
使用原生表达式时需要注意,不同数据库的SQL语法存在差异,比如MySQL的NOW()函数在PostgreSQL中是CURRENT_TIMESTAMP,编写代码时要确认当前使用的数据库类型,避免语法错误。
另外,不要过度使用原生表达式,Eloquent本身提供的查询方法已经能满足大部分常规需求,过度使用原生表达式会降低代码的可移植性,也会增加维护难度。只有在ORM无法实现的复杂查询场景下,才建议使用Raw Expressions。
总结
Eloquent Raw Expressions是Laravel中处理复杂数据库查询的重要工具,通过DB::raw()方法可以方便地调用各类数据库原生函数。使用时要注意做好参数绑定避免SQL注入,同时尽量控制使用范围,保证代码的可维护性。掌握原生表达式的使用方法,能让开发者在Laravel项目中更灵活地操作数据库,应对各种复杂的业务查询需求。
PHPEloquent_Raw_ExpressionsLaravel数据库函数调用修改时间:2026-06-19 15:06:39