CodeIgniter如何动态设置自动加载的数据库

时间:2018-01-05 14:50:50

标签: php codeigniter

使用CodeIgniter 3,我自动加载我的数据库配置,现在如何更改动态连接的数据库?我在想使用会话来传递数据库值,但是会话不能在数据库配置文件中使用。

我知道我可以手动加载数据库并对其进行更改,但之后我必须在每个控制器中调用并加载数据库,并且我有大量的控制器,因此我想避免手动设置数据库。

1 个答案:

答案 0 :(得分:1)

可能有多种方法可以做你想要的。此处显示的解决方案使用CodeIgniter的" Hooks"特征。具体来说,它使用" post_controller_constructor" hook以匹配控制器的名称与database.php中定义的特定database configuration

在钩子完成其工作后,应用程序可以使用$this->db->以典型的CI方式调用数据库。例如......

$query = $this->db->get('mytable');

此解决方案基于以下假设:任何给定控制器只需要一个数据库连接。这意味着该控制器中的所有方法(或控制器加载的任何模型)都使用相同的连接。

以下是如何完成的。

application / config / config.php

$config['enable_hooks'] = TRUE;

application / config / hooks.php

$hook['post_controller_constructor'][] = array(
  'class' => '',
  'function' => 'set_db_connection',
  'filename' => 'post_controller_hook.php',
  'filepath' => 'hooks'
);

文件 post_controller_hook.php 是工作完成的地方。它使用控制器名称列表来确定要加载哪个数据库配置。

列表($controller_lists)包含子阵列,这些子阵列按照所需的db配置对控制器名称进行分组。通过每个子阵列进行搜索以找到匹配的控制器名称。找到控制器名称时,该子数组的键是要加载的db config。如果找不到匹配项,则默认为'使用了配置。

$controller_lists数组在这里是硬编码的,但它可以很容易地从配置文件中加载。配置文件可能会使列表更容易维护。

file application / config / post_controller_hook.php

function set_db_connection()
{
    $CI = get_instance();
    $controller = $CI->router->class;
    $loadConfig = 'default';  //if nothing found in lists we're still good

    $controller_lists = array(
        'config2' => ['profile'],
        'config3' => ['discusion', 'home'],
        'config4' => ['suppliers', 'customers', 'inventory', 'orders']
    );

    foreach($controller_lists as $config_name => $list)
    {
        if(in_array($controller, $list))
        {
            $loadConfig = $config_name;
            break;
        }
    }

    $CI->load->database($loadConfig);
}

如果需要,可以添加不为不需要的控制器加载数据库的功能。但我不会去那里。

如前所述,此解决方案使用的假设是,任何给定的控制器只使用一个数据库配置(连接)。如果控制器的某些方法需要使用不同的db配置,则此解决方案变得更加复杂。

将方法添加到搜索中很容易。 set_db_connection()的前几行看起来像这样。

function set_db_connection()
{
    $CI          = get_instance();
    $controller  = $CI->router->class;
    $method      = $CI->router->method;

    if($method !== 'index')
    {
        $controller .= '/'.$method; //append method name
    }
    $loadConfig = 'default';  //if nothing found in lists we're still good

所以现在$controller将会拥有“控制器/方法”,或者只是“控制器”#39;如果要调用index()

考虑一个名为Viewstate的控制器,它有三种方法

class Viewstate extends CI_Controller
{
    public function index(){
        //uses db 'config4' 
    }
    public function report(){
        //uses db 'Config2'
    }
    public function process(){
        //uses db 'Config3' 
    }
}

我们必须包含每个' viewstate / method'在这样的子阵列中。

    $controller_lists = array(
        'config2' => ['profile', 'viewstate/report'],
        'config3' => ['disscusion', 'home', 'viewstate/process'],
        'config4' => ['viewstate', 'customers', 'inventory', 'orders']
    );

    //the rest of the function is as shown earlier

任何' viewstate / method'不在搜索列表中,它将被分配默认值' db config。因此,对viewstate的各种需求进行排序很容易。

问题在于每个'控制器/方法'现在,网站必须包含在搜索列表中。如果Profile控制器有十个方法,则每个组合现在必须位于config2子数组中。因此,如果有很多控制器和控制器/方法,这个解决方案是一个糟糕的选择。可能有一种优雅的方式解决这个问题,但这可能是一个新问题的话题。