通过前面几篇教程的预热,我们已经连接上数据库,创建好了数据表,填充好了数据,接下来,就是在 Laravel 应用中实现对数据库的增删改查了。
Laravel 数据库功能的核心就是提供流式接口与数据库进行交互的查询构建器(Query Builder),支持 MySQL、Postgres、SQLite 和 SQL Server 等常见的数据库管理系统,没有特别说明的话,我们的所有教程都基于 MySQL。
注:关于流式接口可以查看流接口模式了解明细。
使用 DB 门面执行原生 SQL 语句
如果你之前没有使用过任何 PHP 框架,只是对数据库和 SQL 语句有一些初步了解,或者你的 SQL 语句过于复杂,而你又对编写安全的 SQL 语句很有信心,我们可以直接通过 DB
门面提供的方法执行原生的 SQL 语句,DB
门面既可以用于构建查询构建器方法链,也可以用于原生语句的执行。
原生 Statement 语句
我们可以通过 DB
门面提供的 statement
方法执行原生的 SQL Statement 语句,比如创建、删除、修改数据表操作:
DB::statement('drop table `users`');
DB::statement('create table `users` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL)');
只不过在 Laravel 中,我们不推荐这么做,因为这些对数据表结构的操作可以通过数据库迁移功能来实现,而且那样做的话可维护性更好。
原生查询语句
接下来,我们进入正题,正式开始对数据表数据的增删改查操作。DB
门面提供了一个 select
语句帮助我们对数据表进行查询:
$users = DB::select('select * from `users`');
该方法返回包含所有查询结果的 stdClass
对象数组:
如果你想要进一步指定查询条件,此时就要考虑 SQL 语句的安全性,比如规避 SQL 注入攻击,尤其是这个查询条件是用户通过请求参数指定的。由于 Laravel 数据库功能底层基于 PHP 的 PDO 实现,因此我们可以借助 PDO 的参数绑定功能来防范 SQL 注入,所以对于指定查询条件的 SQL 查询语句,可以这么实现:
代码语言:javascript复制$name = '学院君';
$users = DB::select('select * from `users` where `name` = ?', [$name]);
我们还可以对绑定参数进行命名以便更加明确绑定了哪个参数:
代码语言:javascript复制$users = DB::select('select * from `users` where `name` = :name', ['name' => $name]);
上面两条语句返回结果一样,此时返回的就是指定查询条件的结果:
如果你要设置多个查询条件,添加多个绑定参数即可。
原生插入语句
想要在数据库中插入一条记录,通过 DB
门面提供的 insert
语句即可:
$name = str_random(10);
$email = str_random(10) . '@163.com';
$password = bcrypt('secret');
$flag = DB::insert('insert into `users` (`name`, `email`, `password`) values (?, ?, ?)', [$name, $email, $password]);
如果插入成功,返回 true
,插入失败,则抛出 QueryException
异常。
原生更新语句
要修改数据表记录,可以通过 DB
门面提供的 update
方法:
$name = str_random(8);
$id = 8;
$affectedRows = DB::update('update `users` set `name` = ? where id = ?', [$name, $id]);
如果更新成功,返回受影响行数,如果更新数据与原记录数据一样,则返回0
,如果更新出错,则抛出 QueryException
异常。
原生删除语句
要删除数据表记录,可以通过 DB
门面的 delete
方法实现:
$id = 8;
$affectedRows = DB::delete('delete from `users` where id = ?', [$id]);
和更新语句一样,如果删除成功,该方法返回受影响行数,删除记录不存在,返回 0
,删除出错,抛出 QueryException
异常。
友情提示:更新语句和删除语句一定要谨慎注意
where
条件,否则很容器由于疏忽更新了所有数据或删除了所有数据,后果不堪设想!
使用查询构建器进行增删改查
接下来,我们开始介绍 Laravel 数据库功能的核心组件 —— 查询构建器(说是核心,是因为 Eloquent 模型的底层也是基于这个查询构建器),日常开发中,我们与数据库的交互基本都是直接或间接通过它来完成的。
查询构建器也是基于 DB
门面的,只不过需要调用其提供的 table
方法构建一个基于指定数据表的查询构建器。下面我们就通过查询构建器来依次实现上面通过 DB
门面执行原生 SQL 语句完成的增删改查功能。
查询记录
要查询指定数据表中的所有记录,可以通过以下方式实现:
代码语言:javascript复制$users = DB::table('users')->get();
该方法返回的是一个包含所有查询结果的 stdClass
集合:
如果要指定查询条件,可以通过 where
实现:
$name = '学院君';
$users = DB::table('users')->where('name', $name)->get();
使用查询构建器进行查询,无需手动设置参数绑定来规避 SQL 注入攻击,因为 Laravel 底层会帮助我们自动实现参数绑定,所以推荐使用查询构建器进行数据库操作。
上述代码返回的也是包含指定查询结果的 stdClass
集合:
有时候我们可能希望返回查询结果中的第一条记录,这可以通过将 get
方法替换为 first
方法来实现:
$user = DB::table('users')->where('name', $name)->first();
这样,返回的就是一个单个 stdClass
对象了:
默认返回所有字段,要指定查询的字段,可以通过 select
方法来实现:
$user = DB::table('users')->select('id', 'name', 'email')->where('name', $name)->first();
返回结果如下:
插入记录
要通过查询构建器插入一条记录,也很简单,通过 insert
方法即可:
$flag = DB::table('users')->insert([
'name' => str_random(10),
'email' => str_random(8) . '@163.com',
'password' => bcrypt('secret')
]);
如果想要在插入之后获取对应记录的主键 ID,将 insert
方法改为调用 insertGetId
方法:
$userId = DB::table('users')->insertGetId([
'name' => str_random(10),
'email' => str_random(8) . '@qq.com',
'password' => bcrypt('secret')
]);
查询构建器还支持一次插入多条记录:
代码语言:javascript复制DB::table('users')->insert([
['name' => str_random(10), 'email' => str_random(8) . '@qq.com', 'password' => bcrypt('123')],
['name' => str_random(10), 'email' => str_random(8) . '@qq.com', 'password' => bcrypt('456')],
['name' => str_random(10), 'email' => str_random(8) . '@qq.com', 'password' => bcrypt('789')],
]);
同样,如果插入出错,抛出 QueryException
异常,如果是一次插入多条记录的话,会整体中断,一条都不会插进去。
更新记录
更新数据库记录通过 update
方法来完成,我们可以在该方法中传入待修改字段及对应修改值数组:
$id = 11;
$affectedRows = DB::table('users')->where('id', '>', $id)->update(['name' => str_random(8)]);
同样,该方法返回的也是受影响行数,具体逻辑和原生更新语句一样,不再赘述,我们可以通过 where
方法来指定过滤条件。
注:
where
方法第二个参数省略的话,默认是=
,如果不是相等条件,需要手动指定该参数值,比如>
表示大于,<
表示小于,和比较运算符一致。
如果是数值字段的更新的话,Laravel 还为我们提供了 increment
和 decrement
方法用于快速进行数值增减,默认步长是 1
,当然你可以通过第二个参数指定步长值:
DB::table('posts')->where('id', 100)->increment('views'); // views 1
DB::table('posts')->where('id', 100)->increment('views', 5); // views 5
DB::table('posts')->where('id', 100)->decrement('votes'); // votes-1
删除记录
通过查询构建器删除记录可以通过 delete
方法来实现:
$id = 11;
$affectedRows = DB::table('users')->where('id', '>=', $id)->delete();
同样,我们通过 where
方法指定删除 id >= 11
的记录,delete
方法返回受影响行数,具体逻辑和原生删除语句也是一样的。
如果我们想要清空整张数据表,可以通过不指定 where 条件来实现:
代码语言:javascript复制$affectedRows = DB::table('users')->delete();
如果我们还想在清空记录之后重置自增 ID,可以通过 truncate
方法来实现:
$affectedRows = DB::table('users')->truncate();
好了,关于简单的数据库增删改查操作我们先介绍到这里,对于更加复杂的查询操作(连接、分页、子查询等),以及数据库事务的实现,我们将在下一篇教程中展开。