Laravel 文档阅读:数据库起步
简介
Laravel 让开发者与多种数据库的交互变得非常简单,主要是利用 查询语句构造器 和 Eloquent ORM 帮您产生与业务逻辑对应的原生 SQL 语句,避免了开发者手动书写 SQL 语句带来的烦恼。现支持的数据库如下:
- MySQL
- Postgres
- SQLite
- SQL Server
配置
数据库配置文件是 config/database.php
。你可以根据实际情况,修改或添加你的数据库信息,指定默认使用的数据库连接(database connections)。
配置 SQLite
配置 SQLite 需要先创建一个数据库,使用 touch database/database.sqlite
创建,然后再配置你的环境变量——使用绝对路径指向这个新创建的数据库。
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite
配置 SQL Server
Laravel 在配置文件 config/database.php
中,已经为您预设了 SQL Server 的连接信息,只需要按照实际情况修改即可:
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
],
读 & 写连接
有时,您希望项目使用两种数据库——一种负责读,也就是用来执行 select
语句;另一种负责写,用来执行 insert
、update
和 delete
语句。Laravel 使之变得轻而易举,无论您是使用原生查询、查询语句构造器还是Eloquent ORM,都会始终使用正确的连接。
具体读 & 写连接的配置方式,看下面的例子可知:
'mysql' => [
'read' => [
'host' => '192.168.1.1',
],
'write' => [
'host' => '196.168.1.2'
],
'driver' => 'mysql',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
],
我们为配置信息添加了两个键:read
和 write
。两个键里又包含 host
键。在 mysql
中,其余的配置信息是读 & 写连接共用的配置信息。
在上面例子里,192.168.1.1
这台主机用来「读」, 196.168.1.2
这台主机用来「写」。而其余像用户名、密码、数据库编码等都是两个连接共用的配置。
使用多数据库连接
DB
门面提供了 connection
方法,用来获得某个连接。用它就可以实现使用多数据库连接的需求。给 connection
传递是一个「连接名」,这个连接名必然是要在 config/database.php
里配置的。
$users = DB::connection('foo')->select(...);
您可以用连接实例的 getPdo
方法获得底层 PDO
实例。
$pdo = DB::connection()->getPdo();
执行原生 SQL 查询
使用 DB
门面可以完成每种类型的查询:select
、update
、insert
、delete
和 statement
。
执行 select
查询
使用 DB
门面的 select
方法可执行查询:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show a list of all of the application's users.
*
* @return Response
*/
public function index()
{
$users = DB::select('select * from users where active = ?', [1]);
return view('user.index', ['users' => $users]);
}
}
select
方法的第一个参数就是原生的 SQL 语句,第二个参数是绑定到语句的参数。绑定的参数通常是 where
子句约束条件,这可保护程序免受 SQL 注入危害。
select
方法返回一个结果数组,每个数组成员都是一个 PHP StdClass
对象:
foreach ($users as $user) {
echo $user->name;
}
使用命名参数
你可以选择使用命名参数的形式代替 ?
占位符:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
执行 insert
语句
使用 DB
门面的 insert
方法插入数据。形如 select
方法,DB:insert
的第一个参数是原生 SQL 语句,第二个参数是绑定参数:
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
执行 update
语句
update
方法用来更新数据库中已存在的记录,返回的结果是更新的记录数目。
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
执行 delete
语句
update
方法用来从数据库中删除记录,类似 update
方法,返回的结果是删除的记录数目。
执行一般语句
「一般语句」指没有返回结果的 SQL 语句。对于这类操作,可以使用 DB
门面上的 statement
方法。
DB::statement('drop table users');
监听查询事件
如果你要查阅 Laravel 底层执行的 SQL 语句,可以使用 listen
方法,这个方法会在程序执行 SQL 语句时调用。这对 debug 程序和记录 SQL 语句非常有用。你可以在服务提供者 AppServiceProvider
中注册、监听查询事件。
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
数据库事务
你可以用 DB
门面的 transaction
方法在一个事务里执行一系列操作。如果事务闭包里抛出异常,那么事务就会自动回滚。如果闭包执行成功,那么事务就会自动提交。使用 transaction
方法就无需手动回滚或者提交事务了:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
解决死锁
transaction
方法还要第二个参数可供指定——当死锁发生时,事务最大的尝试次数。一旦超过这个指定次数,就会抛出异常:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
}, 5);
手动使用事务
如果你要完全手动控制事务的回滚和提交,就要用 DB
门面的 beginTransaction
方法了:
DB::beginTransaction();
使用 rollBack
方法回滚事务:
DB::rollBack();
最后,使用 commit
方法提交事务:
DB::commit();
本作品采用《CC 协议》,转载必须注明作者和本文链接
我觉得数据库事务这个使用的时候有点不够优雅。。。。
@xhh110 仁者见仁 ;)
@redrain 这个我真不知道,
options
的作用是什么呢?@zhangbao
$pdo = new PDO($dsn, $username, $password, $options);
@redrain 官方文档里并没有这个说明。谢谢你的提示。
@zhangbao 不谢,官方文档没写到的 其实很多