Laravel 官方支持以下数据库:
MySQL / MariaDB
PostgreSQL
SQLite
SQL Server
你可以使用相同的连接配置来执行原生 SQL、Query Builder 或 Eloquent ORM。
数据库配置集中存放在 config/database.php。
你可以通过 default 选择默认连接名,通过 connections 定义每个连接的详情。
// config/database.php
'default' => env ( 'DB_CONNECTION' , 'sqlite' ),
'connections' => [
'mysql' => [
'driver' => 'mysql' ,
'host' => env ( 'DB_HOST' , '127.0.0.1' ),
'port' => env ( 'DB_PORT' , '3306' ),
'database' => env ( 'DB_DATABASE' , 'laravel' ),
'username' => env ( 'DB_USERNAME' , 'root' ),
'password' => env ( 'DB_PASSWORD' , '' ),
],
],
在 .env 中至少要设置如下内容:
DB_CONNECTION =mysql
DB_HOST =127.0.0.1
DB_PORT =3306
DB_DATABASE =app
DB_USERNAME =app_user
DB_PASSWORD =secret
如果使用 SQLite,请设置 DB_CONNECTION=sqlite 与 DB_DATABASE 的路径。
读写分离
如果希望将读操作(SELECT)与写操作(INSERT / UPDATE / DELETE)分派到不同主机,请在同一连接内配置 read 与 write。
'mysql' => [
'driver' => 'mysql' ,
'read' => [
'host' => [ '10.0.0.10' , '10.0.0.11' ],
],
'write' => [
'host' => [ '10.0.0.20' ],
],
'sticky' => true ,
'port' => env ( 'DB_PORT' , '3306' ),
'database' => env ( 'DB_DATABASE' , 'laravel' ),
'username' => env ( 'DB_USERNAME' , 'root' ),
'password' => env ( 'DB_PASSWORD' , '' ),
],
将 sticky 设置为 true 后,在同一请求内写入后的读取会固定使用写连接。
在存在副本延迟的架构中,启用 sticky 可以降低刚写入后读到旧数据的风险。
Pooled PostgreSQL 连接
当你使用 PgBouncer 之类以事务模式提供连接池的托管 PostgreSQL 服务时,请配置 pooled 与 direct 选项。
'pgsql' => [
'driver' => 'pgsql' ,
// ...
'pooled' => env ( 'DB_POOLED' , false ),
'direct' => array_filter ([
'host' => env ( 'DB_DIRECT_HOST' ),
'port' => env ( 'DB_DIRECT_PORT' ),
'username' => env ( 'DB_DIRECT_USERNAME' ),
'password' => env ( 'DB_DIRECT_PASSWORD' ),
'sslmode' => env ( 'DB_DIRECT_SSLMODE' ),
]),
],
启用 pooled 后,Laravel 会自动进行路由分派。
操作 使用的连接 应用查询 pooled(自动启用模拟 prepare) 迁移 / db:wipe / db:show / db:table direct(自动) php artisan dbdirect(默认),可通过 --pooled 切换至 pooled
如果在应用代码中希望显式使用 direct 连接,请在连接名上追加 ::direct 后缀。
DB :: connection ( 'pgsql::direct' ) -> statement ( 'create extension if not exists "uuid-ossp"' );
多数据库连接
你可以在 config/database.php 中定义多个连接,并通过 DB::connection() 进行切换。
use Illuminate\Support\Facades\ DB ;
$users = DB :: connection ( 'sqlite' ) -> select ( 'select * from users' );
$pdo = DB :: connection ( 'pgsql' ) -> getPdo ();
执行 SQL 查询
DB 门面按不同的查询类型提供了专用方法。
use Illuminate\Support\Facades\ DB ;
$users = DB :: select ( 'select * from users where active = ?' , [ 1 ]);
DB :: insert ( 'insert into users (name, email) values (?, ?)' , [ 'Taylor' , '[email protected] ' ]);
$affected = DB :: update ( 'update users set votes = 100 where name = ?' , [ 'Taylor' ]);
$deleted = DB :: delete ( 'delete from sessions where user_id = ?' , [ 1 ]);
DB :: statement ( 'drop table temporary_imports' );
不要将用户输入直接拼接到 SQL 字符串中。请务必使用绑定参数,避免 SQL 注入。
查询监听
如果要跟踪已执行的 SQL,请在服务提供者的 boot() 中注册 DB::listen()。
use Illuminate\Database\Events\ QueryExecuted ;
use Illuminate\Support\Facades\ DB ;
public function boot () : void
{
DB :: listen ( function ( QueryExecuted $query ) {
logger () -> debug ( 'SQL executed' , [
'sql' => $query -> toRawSql (),
'time_ms' => $query -> time ,
]);
});
}
如果需要将多个更新作为一个单元处理,请使用 DB::transaction()。
一旦发生异常,Laravel 会自动回滚。
use Illuminate\Support\Facades\ DB ;
DB :: transaction ( function () {
DB :: update ( 'update users set votes = 1' );
DB :: delete ( 'delete from posts where archived = 1' );
});
如果需要死锁重试,可以指定 attempts。
DB :: transaction ( function () {
// ...
}, attempts : 5 );
如果需要手动控制,可以使用 beginTransaction / rollBack / commit。
DB :: beginTransaction ();
try {
DB :: update ( 'update accounts set balance = balance - 100 where id = ?' , [ 1 ]);
DB :: update ( 'update accounts set balance = balance + 100 where id = ?' , [ 2 ]);
DB :: commit ();
} catch ( \ Throwable $e ) {
DB :: rollBack ();
throw $e ;
}
下一步
Query Builder 学习如何借助连接配置安全地构建查询。
Migrations 学习如何对已连接数据库的表结构进行版本管理。
Seeding 学习如何以可复现的方式填充开发与测试数据。