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

CodeIgniter根据Session值全局自动切换数据库的实现方法

全局实现CodeIgniter根据Session自动切换数据库的方案

重复写切换逻辑确实挺烦的,咱们可以通过扩展CodeIgniter核心类或者使用钩子来实现全局自动处理,不用每个模型/控制器都重复代码。下面给你几个实用的方案:

方案一:扩展CI_Model(推荐,模型层面统一处理)

CodeIgniter允许我们扩展核心的CI_Model类,让所有自定义模型都继承这个扩展后的父类,这样切换数据库的逻辑只需要写一次,所有模型自动复用。

  1. 在application/core目录下创建MY_Model.php(注意命名要和你配置里的subclass_prefix一致,默认是MY_):
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Model extends CI_Model {
    public function __construct() {
        parent::__construct();
        
        // 从Session获取目标数据库名
        $target_db = $this->session->userdata('dbname');
        
        if (!empty($target_db)) {
            // 读取默认数据库配置
            $db_config = $this->config->item('database');
            // 替换数据库名称
            $db_config['database'] = $target_db;
            
            // 初始化新连接并替换默认的db实例
            $this->db = $this->load->database($db_config, TRUE);
        }
    }
}
  1. 之后所有模型都继承MY_Model而非CI_Model,比如你的News_model:
<?php
class News_model extends MY_Model {
    public function __construct() {
        parent::__construct();
        // 这里不用再写切换逻辑了,父类已经处理完成
    }

    // 你的模型业务方法...
}

这样每次加载模型时,都会自动执行父类构造函数完成数据库切换。

方案二:扩展CI_Controller(控制器层面全局处理)

如果需要在控制器层面统一处理,或者控制器本身也要用到切换后的数据库,可以扩展核心控制器:

  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();
        
        $target_db = $this->session->userdata('dbname');
        
        if (!empty($target_db)) {
            $db_config = $this->config->item('database');
            $db_config['database'] = $target_db;
            // 替换全局的db连接实例
            $this->db = $this->load->database($db_config, TRUE);
        }
    }
}
  1. 所有控制器继承MY_Controller:
<?php
class News extends MY_Controller {
    public function __construct() {
        parent::__construct();
        $this->load->model('News_model');
        // 此时模型使用的已经是切换后的数据库连接
    }
}

方案三:使用CodeIgniter钩子(全请求拦截处理)

如果想在请求初始化阶段就完成数据库切换,不管后续加载控制器还是模型,都能直接用切换后的连接,可以用钩子:

  1. 先在application/config/config.php开启钩子:
$config['enable_hooks'] = TRUE;
  1. 在application/config/hooks.php添加钩子配置:
$hook['post_controller_constructor'] = array(
    'class'    => 'DbSwitchHook',
    'function' => 'switch_database',
    'filename' => 'DbSwitchHook.php',
    'filepath' => 'hooks',
    'params'   => array()
);
  1. 在application/hooks目录创建DbSwitchHook.php:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class DbSwitchHook {
    public function switch_database() {
        $CI =& get_instance();
        
        $target_db = $CI->session->userdata('dbname');
        
        if (!empty($target_db)) {
            $db_config = $CI->config->item('database');
            $db_config['database'] = $target_db;
            $CI->db = $CI->load->database($db_config, TRUE);
        }
    }
}

这个钩子会在控制器构造函数执行后触发,确保Session已加载,之后所有模型和控制器使用的都是切换后的数据库连接。

注意事项

  • 务必确保Session已自动加载:在application/config/autoload.php中添加$autoload['libraries'] = array('session');,否则无法获取到dbname值。
  • 如果你的数据库有特殊配置(比如不同用户名/密码),可以根据需求调整$db_config的参数。
  • 测试时要保证Session中的dbname是存在且有效的数据库名称,避免连接失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:49:31