Laravel不支持运行时动态切换数据库驱动,但可通过配置多个连接名实现多库、读写分离和租户隔离;所有连接需在config/database.php的'connections'中定义,连接名全局唯一,'driver'可不同,切换仅限于已注册的连接名。
Laravel 本身不支持运行时动态切换数据库驱动(比如从 mysql 切到 pgsql),但可以动态切换连接名(connection name)——这是实现多库、读写分离、租户隔离的正确路径。
所有连接都写在 config/database.php 的 'connections' 数组里,每个键是连接名(如 'mysql'、'mysql_read'、'tenant_123'),值是完整配置。关键点:
'driver' 决定底层用哪个 PDO 驱动,同一应用中不同连接可使用不同驱动(比如主库 mysql,日志库 sqlite)'database' 和 'host' 等参数可从环境变量读取,方便多环境管理return [
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'mysql' => [
'
driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
'mysql_read' => [
'driver' => 'mysql',
'host' => env('DB_READ_HOST', '192.168.1.10'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
],
];
切换的是连接名(connection name),不是驱动类型。Laravel 的 DB::connection() 和模型的 $connection 属性都只接受已注册的连接名。
DB::connection('mysql_read')->table('users')->get()
protected $connection = 'mysql_read';
User::on('tenant_'.$tenantId)->get(),前提是该连接名已在 config/database.php 或运行时用 Config::set() 注册过on() 只影响当前查询,不会改变模型默认连接;未调用 on() 时仍走 $connection 或全局 default
Laravel 自带的读写分离机制,依赖你明确声明哪些连接是 “read”、哪些是 “write”,并统一挂到一个逻辑连接名下(如 'mysql'),而不是靠中间件或 DB 类自动判断 SQL 类型。
config/database.php 中,把 'mysql' 改成数组形式,包含 'read' 和 'write' 子键SELECT
SELECT 查询(INSERT/UPDATE/DELETE)强制走 'write' 配置DB::table() 和未指定 $connection 的 Eloquent 生效;一旦用了 on('xxx'),就绕过读写分离逻辑'mysql' => [
'read' => [
'host' => ['192.168.1.10', '192.168.1.11'],
],
'write' => [
'host' => ['192.168.1.5'],
],
'driver' => 'mysql',
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
],
可以用 Config::set('database.connections.tenant_123', [...]) 在请求中注册新连接,但有硬性限制:
DB::connection('tenant_123') 之前完成注册,否则 Laravel 会报 InvalidArgumentException: Database [tenant_123] not configured.
'database'、'username' 等字段不能含非法字符,尤其注意租户 ID 是否被注入恶意内容Config::set()
tenant_001 ~ tenant_100),启动时全部加载驱动类型是静态绑定的,改不了;连接名才是你真正能控制的开关。别试图在运行时把 mysql 驱动替换成 sqlsrv,那会直接报错。
# mysql
# sqlite
# database
# 数据库
# 多个
# 不支持
# 会报
# 绑定
# 的是
# 而不是
# 这是
# 如果你
# 连接池
# table
# default
# php
# word
# laravel
# 路由
# 环境变量
# red
# sql
# 中间件
# select
# pdo
# protected
# delete
# 才是