数据库:入门
介绍
Laravel 使得与数据库的交互变得极其简单,无论是使用原生 SQL、流畅的查询构建器还是 Eloquent ORM。目前,Laravel 支持四种数据库:
- MySQL
- Postgres
- SQLite
- SQL Server
配置
应用程序的数据库配置位于 config/database.php
。在此文件中,您可以定义所有的数据库连接,并指定默认使用哪个连接。此文件中提供了大多数支持的数据库系统的示例。
默认情况下,Laravel 的示例环境配置已准备好与 Laravel Homestead 一起使用,后者是一个方便的虚拟机,用于在本地机器上进行 Laravel 开发。当然,您可以根据本地数据库的需要自由修改此配置。
SQLite 配置
在使用诸如 touch database/database.sqlite
之类的命令创建新的 SQLite 数据库后,您可以通过使用数据库的绝对路径轻松配置环境变量以指向此新创建的数据库:
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite
SQL Server 配置
Laravel 开箱即支持 SQL Server;然而,您需要将数据库的连接配置添加到 config/database.php
配置文件中:
'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' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
注意,配置数组中添加了两个键:read
和 write
。这两个键都有一个包含单个键 host
的数组值。read
和 write
连接的其余数据库选项将从主 mysql
数组中合并。
如果您希望覆盖主数组中的值,只需将项目放在 read
和 write
数组中即可。因此,在这种情况下,192.168.1.1
将用作“读”连接的主机,而 192.168.1.2
将用作“写”连接的主机。数据库凭据、前缀、字符集和主 mysql
数组中的所有其他选项将在两个连接之间共享。
使用多个数据库连接
使用多个连接时,您可以通过 DB
facade 上的 connection
方法访问每个连接。传递给 connection
方法的 name
应对应于 config/database.php
配置文件中列出的连接之一:
$users = DB::connection('foo')->select(...);
您还可以使用连接实例上的 getPdo
方法访问原始的底层 PDO 实例:
$pdo = DB::connection()->getPdo();
运行原生 SQL 查询
配置数据库连接后,您可以使用 DB
facade 运行查询。DB
facade 为每种类型的查询提供方法:select
、update
、insert
、delete
和 statement
。
运行选择查询
要运行基本查询,您可以使用 DB
facade 上的 select
方法:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 显示应用程序所有用户的列表。
*
* @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
facade 上的 insert
方法。与 select
类似,此方法将原生 SQL 查询作为第一个参数,绑定作为第二个参数:
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
运行更新语句
update
方法应用于更新数据库中的现有记录。语句影响的行数将被返回:
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
运行删除语句
delete
方法应用于从数据库中删除记录。与 update
类似,影响的行数将被返回:
$deleted = DB::delete('delete from users');
运行通用语句
某些数据库语句不返回任何值。对于这些类型的操作,您可以使用 DB
facade 上的 statement
方法:
DB::statement('drop table users');
监听查询事件
如果您希望接收应用程序执行的每个 SQL 查询,您可以使用 listen
方法。此方法对于记录查询或调试非常有用。您可以在服务提供者中注册查询监听器:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* 启动任何应用程序服务。
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
/**
* 注册服务提供者。
*
* @return void
*/
public function register()
{
//
}
}
数据库事务
您可以使用 DB
facade 上的 transaction
方法在数据库事务中运行一组操作。如果在事务 Closure
中抛出异常,事务将自动回滚。如果 Closure
成功执行,事务将自动提交。使用 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
facade 上的 beginTransaction
方法:
DB::beginTransaction();
您可以通过 rollBack
方法回滚事务:
DB::rollBack();
最后,您可以通过 commit
方法提交事务:
DB::commit();
使用 DB
facade 的事务方法还可以控制查询构建器和Eloquent ORM的事务。