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

CodeIgniter 3如何动态切换自动加载的数据库连接

解决CodeIgniter 3动态切换数据库且避免重复代码的方案

我之前也碰到过一模一样的需求——不想在每个控制器里重复写数据库切换逻辑,这里给你两个实用的解决方案:

方案一:扩展核心控制器(推荐)

通过自定义一个基类控制器,让所有需要切换数据库的业务控制器都继承它,这样切换逻辑只需要写一次:

  1. 在application/core目录下创建MY_Controller.php文件:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Controller extends CI_Controller {

    public function __construct() {
        parent::__construct();
        
        // 确保Session已加载(如果没在autoload配置里自动加载的话)
        if (!isset($this->session)) {
            $this->load->library('session');
        }

        // 从Session读取动态数据库参数
        $db_host = $this->session->userdata('db_host');
        $db_user = $this->session->userdata('db_user');
        $db_pass = $this->session->userdata('db_pass');
        $db_name = $this->session->userdata('db_name');

        // 只有当Session里存在有效参数时才执行切换
        if (!empty($db_host) && !empty($db_name)) {
            $dynamic_db_config = [
                'hostname' => $db_host,
                'username' => $db_user,
                'password' => $db_pass,
                'database' => $db_name,
                'dbdriver' => 'mysqli', // 根据你的数据库驱动调整
                'dbprefix' => '',
                'pconnect' => FALSE,
                'db_debug' => (ENVIRONMENT !== 'production'),
                'char_set' => 'utf8',
                'dbcollat' => 'utf8_general_ci',
                'save_queries' => TRUE
            ];

            // 加载并替换默认的数据库连接
            $this->db = $this->load->database($dynamic_db_config, TRUE);
        }
        // 否则自动使用你配置的默认数据库连接
    }
}
  1. 之后你的业务控制器都继承这个MY_Controller而不是原生的CI_Controller:
class User extends MY_Controller {
    public function profile() {
        // 这里$this->db已经是切换后的数据库连接了
        $user_data = $this->db->get('user_profile')->row();
        // 后续业务逻辑...
    }
}

如果有部分控制器不需要切换数据库,你可以再创建一个Public_Controller继承原生CI_Controller,专门给这类控制器使用。

方案二:使用CodeIgniter钩子

利用钩子的post_controller_constructor事件,在每个控制器初始化完成后自动执行数据库切换,不需要修改现有控制器的继承关系:

  1. 先启用钩子:打开application/config/config.php,设置$config['enable_hooks'] = TRUE;

  2. 在application/config/hooks.php中添加钩子配置:

$hook['post_controller_constructor'] = array(
    'class'    => 'DbSwitcher',
    'function' => 'switchDatabase',
    'filename' => 'DbSwitcher.php',
    'filepath' => 'hooks'
);
  1. 在application/hooks目录下创建DbSwitcher.php文件:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class DbSwitcher {

    public function switchDatabase() {
        $CI =& get_instance();

        // 确保Session可用
        if (!isset($CI->session)) {
            $CI->load->library('session');
        }

        // 从Session获取参数
        $db_host = $CI->session->userdata('db_host');
        $db_name = $CI->session->userdata('db_name');

        if (!empty($db_host) && !empty($db_name)) {
            $dynamic_config = [
                'hostname' => $db_host,
                'username' => $CI->session->userdata('db_user'),
                'password' => $CI->session->userdata('db_pass'),
                'database' => $db_name,
                'dbdriver' => 'mysqli',
                'db_debug' => (ENVIRONMENT !== 'production'),
                'char_set' => 'utf8',
                'dbcollat' => 'utf8_general_ci'
            ];

            // 替换默认数据库连接
            $CI->db = $CI->load->database($dynamic_config, TRUE);
        }
    }
}

如果有个别控制器不需要切换数据库,你可以在钩子类里加判断(比如根据控制器名称跳过)。

注意事项

  • 一定要处理Session参数为空的情况,避免因为参数缺失导致数据库连接失败;
  • 如果你的Session用数据库存储,要确保默认数据库能正常访问,否则Session无法读取;
  • 生产环境建议关闭db_debug,避免暴露敏感的数据库连接信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:15:55