CodeIgniter根据Session值全局自动切换数据库的实现方法
全局实现CodeIgniter根据Session自动切换数据库的方案
重复写切换逻辑确实挺烦的,咱们可以通过扩展CodeIgniter核心类或者使用钩子来实现全局自动处理,不用每个模型/控制器都重复代码。下面给你几个实用的方案:
方案一:扩展CI_Model(推荐,模型层面统一处理)
CodeIgniter允许我们扩展核心的CI_Model类,让所有自定义模型都继承这个扩展后的父类,这样切换数据库的逻辑只需要写一次,所有模型自动复用。
- 在
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); } } }
- 之后所有模型都继承
MY_Model而非CI_Model,比如你的News_model:
<?php class News_model extends MY_Model { public function __construct() { parent::__construct(); // 这里不用再写切换逻辑了,父类已经处理完成 } // 你的模型业务方法... }
这样每次加载模型时,都会自动执行父类构造函数完成数据库切换。
方案二:扩展CI_Controller(控制器层面全局处理)
如果需要在控制器层面统一处理,或者控制器本身也要用到切换后的数据库,可以扩展核心控制器:
- 在
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); } } }
- 所有控制器继承
MY_Controller:
<?php class News extends MY_Controller { public function __construct() { parent::__construct(); $this->load->model('News_model'); // 此时模型使用的已经是切换后的数据库连接 } }
方案三:使用CodeIgniter钩子(全请求拦截处理)
如果想在请求初始化阶段就完成数据库切换,不管后续加载控制器还是模型,都能直接用切换后的连接,可以用钩子:
- 先在
application/config/config.php开启钩子:
$config['enable_hooks'] = TRUE;
- 在
application/config/hooks.php添加钩子配置:
$hook['post_controller_constructor'] = array( 'class' => 'DbSwitchHook', 'function' => 'switch_database', 'filename' => 'DbSwitchHook.php', 'filepath' => 'hooks', 'params' => array() );
- 在
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
相关产品推荐
相关产品推荐

