You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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');
    }
}

注意

  • 模型自定义方法不会触发内置事件,需手动在方法内调用切换逻辑
  • 不适合有大量自定义方法的场景

关键注意事项

  1. 连接缓存:CI4会缓存数据库连接,若频繁切换客户库,可调用\Config\Database::close('client_' . $clientId)关闭闲置连接,避免连接数超限
  2. 客户ID获取:确保当前客户ID的来源可靠(如session、JWT令牌),避免切换到错误数据库
  3. 跨库事务:多数数据库不支持跨库事务,若需同时操作主库和客户库,需拆分事务单独处理

内容的提问来源于stack exchange,提问作者Florianb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 14:38:14