CodeIgniter 4 模型如何自动切换不同数据库连接?
CodeIgniter 4 多模型自动切换数据库方案
针对你需要调用客户模型时自动切换到对应客户数据库、普通模型切回主库的需求,以下几种实用方案可以实现:
方案1:基类模型统一处理(推荐)
创建两个基类模型,分别对应主库和客户库的切换逻辑,所有业务模型继承对应基类即可自动完成数据库切换。
主库基类模型
所有普通业务模型继承此类,初始化时自动切回主库:
<?php namespace App\Models; use CodeIgniter\Model; class MainBaseModel extends Model { public function __construct() { parent::__construct(); // 切换到主数据库 $this->db = \Config\Database::connect('mainDB'); } }
客户库基类模型
所有客户相关模型继承此类,初始化时自动切换到当前客户的数据库:
<?php namespace App\Models; use CodeIgniter\Model; class ClientBaseModel extends Model { public function __construct() { parent::__construct(); // 从业务场景获取当前客户ID(示例从session取,可替换为JWT/请求参数等) $clientId = session()->get('current_client_id'); // 方式1:用预定义的数据库组(需在Config/Database.php中配置client_{id}组) $this->db = \Config\Database::connect('client_' . $clientId); // 方式2:动态构造数据库配置(适用于客户库无预配置的场景) /* $clientDbConfig = [ 'hostname' => 'localhost', 'username' => 'db_user', 'password' => 'db_pass', 'database' => 'client_db_' . $clientId, 'DBDriver' => 'MySQLi', 'charset' => 'utf8', // 其他数据库配置项 ]; $this->db = \Config\Database::connect($clientDbConfig); */ } }
使用示例
// 自动切换到mainDB $normalModel = new \App\Models\NormalModel(); // 继承MainBaseModel $mainData = $normalModel->findAll(); // 自动切换到当前客户的数据库 $clientUsersModel = new \App\Models\ClientUsersModel(); // 继承ClientBaseModel $clientData = $clientUsersModel->findAll();
方案2:自定义服务容器获取模型
如果不想修改模型继承关系,可以在服务容器中封装模型获取逻辑,按需切换数据库:
扩展服务配置
在Config/Services.php中添加自定义服务:
<?php namespace Config; use CodeIgniter\Config\BaseService; class Services extends BaseService { // 获取客户相关模型,自动切换数据库 public static function clientModel(string $modelClass) { $model = new $modelClass(); $clientId = session()->get('current_client_id'); $model->db = \Config\Database::connect('client_' . $clientId); return $model; } }
使用示例
// 获取客户模型,自动切换到客户库 $clientUsersModel = Services::clientModel(\App\Models\ClientUsersModel::class); $clientData = $clientUsersModel->findAll(); // 获取普通模型,默认使用mainDB $normalModel = model(\App\Models\NormalModel::class); $mainData = $normalModel->findAll();
方案3:模型事件触发切换(适合特定操作)
如果仅需要在CRUD操作时切换数据库,可以利用CI4的模型事件,在操作前后切换数据库:
<?php namespace App\Models; use CodeIgniter\Model; class ClientUsersModel extends Model { protected $table = 'users'; protected $allowedFields = ['name', 'email']; public function __construct() { parent::__construct(); // 注册操作前切换事件 $this->beforeFind = [$this, 'switchToClientDB']; $this->beforeInsert = [$this, 'switchToClientDB']; $this->beforeUpdate = [$this, 'switchToClientDB']; $this->beforeDelete = [$this, 'switchToClientDB']; // 可选:操作后切回主库 $this->afterFind = [$this, 'switchBackToMainDB']; } public function switchToClientDB() { $clientId = session()->get('current_client_id'); $this->db = \Config\Database::connect('client_' . $clientId); } public function switchBackToMainDB() { $this->db = \Config\Database::connect('mainDB'); } }
注意
- 模型自定义方法不会触发内置事件,需手动在方法内调用切换逻辑
- 不适合有大量自定义方法的场景
关键注意事项
- 连接缓存:CI4会缓存数据库连接,若频繁切换客户库,可调用
\Config\Database::close('client_' . $clientId)关闭闲置连接,避免连接数超限 - 客户ID获取:确保当前客户ID的来源可靠(如session、JWT令牌),避免切换到错误数据库
- 跨库事务:多数数据库不支持跨库事务,若需同时操作主库和客户库,需拆分事务单独处理
内容的提问来源于stack exchange,提问作者Florianb
相关产品推荐
相关产品推荐

