查询构建器(Query Builder)是 Laravel 提供的用于数据库交互的流畅接口,它允许你使用 PHP 方法链来构建 SQL 查询,同时自动防止 SQL 注入。 相比原生 SQL,查询构建器更安全、更易读,并且与数据库无关。
查询构建器位于 Illuminate\Database\Query\Builder 类中,通过 DB Facade 的 table 方法获取实例。
它支持几乎所有 SQL 操作,并提供了流畅的链式调用语法。
使用 DB::table() 方法,传入表名,即可获得该表的查询构建器实例:
use Illuminate\Support\Facades\DB;
$users = DB::table('users')->get();
get() 方法返回一个包含所有查询结果的集合(Collection),每条记录是一个 PHP 对象:
$users = DB::table('users')->get();
foreach ($users as $user) {
echo $user->name;
}
first() 方法只返回结果集的第一条,没有记录时返回 null:
$user = DB::table('users')->where('id', 1)->first();
echo $user->name;
还可以使用 find($id) 直接根据主键查找:
$user = DB::table('users')->find(1);
value() 方法返回单条记录的单个字段值:
$email = DB::table('users')->where('name', 'John')->value('email');
pluck() 方法获取一列的值,返回集合:
$names = DB::table('users')->pluck('name');
// ['John', 'Jane', ...]
// 可指定键名
$users = DB::table('users')->pluck('name', 'id');
// [1 => 'John', 2 => 'Jane', ...]
基本 where 方法接受三个参数:字段、操作符、值:
$users = DB::table('users')
->where('age', '>', 18)
->get();
如果只传两个参数,操作符默认为 =:
$users = DB::table('users')->where('active', 1)->get();
可以链式调用多个 where,它们默认使用 AND 连接:
$users = DB::table('users')
->where('active', 1)
->where('age', '>=', 18)
->get();
orWhere 用于添加 OR 条件:
$users = DB::table('users')
->where('active', 1)
->orWhere('age', '>=', 18)
->get();
whereBetween、whereIn、whereNull 等:
// 范围查询
$users = DB::table('users')->whereBetween('age', [18, 30])->get();
// IN 查询
$users = DB::table('users')->whereIn('id', [1, 2, 3])->get();
// NULL 查询
$users = DB::table('users')->whereNull('email_verified_at')->get();
// 日期查询
$users = DB::table('users')->whereDate('created_at', '2024-01-01')->get();
使用闭包创建嵌套的 where 条件:
$users = DB::table('users')
->where('active', 1)
->where(function ($query) {
$query->where('age', '>', 30)
->orWhere('name', 'like', 'John%');
})
->get();
生成的 SQL:SELECT * FROM users WHERE active = 1 AND (age > 30 OR name LIKE 'John%')
查询构建器提供了 count、max、min、avg、sum 等聚合方法:
$count = DB::table('users')->count(); // 总记录数
$maxAge = DB::table('users')->max('age'); // 最大年龄
$avgScore = DB::table('scores')->avg('score'); // 平均分
$total = DB::table('orders')->sum('amount'); // 总金额
orderBy 方法:
$users = DB::table('users')
->orderBy('name', 'asc')
->orderBy('age', 'desc')
->get();
$users = DB::table('users')
->select('department', DB::raw('count(*) as total'))
->groupBy('department')
->having('total', '>', 10)
->get();
take / limit 和 skip / offset:
$users = DB::table('users')->limit(10)->get(); // 取前10条
$users = DB::table('users')->skip(5)->take(10)->get(); // 跳过5条,取10条
使用 insert 方法插入单条或多条记录:
// 单条
DB::table('users')->insert([
'name' => 'John',
'email' => 'john@example.com',
'age' => 25
]);
// 多条
DB::table('users')->insert([
['name' => 'John', 'email' => 'john@example.com'],
['name' => 'Jane', 'email' => 'jane@example.com']
]);
使用 insertGetId 获取自增 ID:
$id = DB::table('users')->insertGetId([
'name' => 'John',
'email' => 'john@example.com'
]);
使用 update 方法,返回受影响的行数:
$affected = DB::table('users')
->where('id', 1)
->update(['age' => 30]);
可以使用 increment 和 decrement 快捷增减:
DB::table('users')->where('id', 1)->increment('age', 2); // age + 2
DB::table('users')->where('id', 1)->decrement('age'); // age - 1
// 同时更新其他字段
DB::table('users')->where('id', 1)->increment('age', 1, ['updated_at' => now()]);
delete 方法删除记录,返回受影响行数:
$deleted = DB::table('users')->where('id', 1)->delete();
清空表使用 truncate:
DB::table('users')->truncate();
当需要执行原生 SQL 函数或特定数据库语法时,可以使用 DB::raw():
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->groupBy('status')
->get();
但需要注意,raw 的内容不会被参数绑定,存在 SQL 注入风险,应谨慎使用。Laravel 也提供了更安全的方法,如 whereRaw、orderByRaw 等:
$users = DB::table('users')
->whereRaw('age > ? and active = ?', [18, 1])
->get();
可以使用 toSql() 获取当前查询的 SQL 语句(不带参数绑定):
$sql = DB::table('users')->where('id', 1)->toSql();
// select * from users where id = ?
要查看完整的 SQL 和绑定的参数,可以使用 dd() 或 dump() 配合 get() 等执行方法:
DB::table('users')->where('id', 1)->dd(); // 输出 SQL 和参数并终止
DB::table('users')->where('id', 1)->dump(); // 仅输出,继续执行
还可以启用查询日志:
DB::enableQueryLog();
$users = DB::table('users')->get();
$queries = DB::getQueryLog(); // 返回所有执行过的查询数组
结合所学知识,构建一个简单的用户管理功能:
// 获取所有活跃用户,按年龄降序,取前10名
$activeUsers = DB::table('users')
->where('active', 1)
->orderBy('age', 'desc')
->limit(10)
->get();
// 插入新用户
$newUserId = DB::table('users')->insertGetId([
'name' => 'New User',
'email' => 'new@example.com',
'active' => 1,
'created_at' => now(),
]);
// 更新用户邮箱
DB::table('users')
->where('id', $newUserId)
->update(['email' => 'updated@example.com']);
// 删除不活跃用户
$deleted = DB::table('users')
->where('active', 0)
->delete();
DB::raw 或确保名称正确。
where、insert 等方法时是安全的。但使用 DB::raw 或 whereRaw 时需手动处理参数绑定。
toSql() 获取带占位符的 SQL,或者使用 dd()、dump() 查看带绑定的完整 SQL。也可以启用查询日志 DB::enableQueryLog() 并获取 DB::getQueryLog()。
查询构建器是 Laravel 中处理数据库查询的核心工具,它提供了流畅的接口和丰富的条件方法,让开发者能够轻松构建复杂的 SQL 语句。 掌握这些基础操作后,下一章我们将学习更高级的查询技巧,如连接查询、子查询、联合查询等。