CakePHP 3动态数据库连接

时间:2018-01-21 22:46:41

标签: php database cakephp database-connection config

在控制器中我想更改我的默认数据库连接,这样我就可以访问不同的数据库。它曾经工作,我在AppController中创建了一个函数,在需要时在每个控制器中调用它,包含以下内容:

ConnectionManager::config('database', [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => 'localhost',
            'username' => $username,
            'password' => $password,
            'database' => $database,
            'encoding' => 'utf8',
            'timezone' => 'UTC',
            'cacheMetadata' => true,
        ]); 

ConnectionManager::alias('database', 'default');

我创建了一个新的数据库连接,称之为'database',并且别名默认为此连接,这样将使用此连接而不是默认连接。但是,当我打印

$this->{$modelName}->connection()->config();

它仍然提供默认连接。并且表示该表不存在的错误确认我不在新连接的数据库中。

2 个答案:

答案 0 :(得分:0)

仅在表实例化时间

选取别名

即时连接通常可以正常工作,但模型/表类只在实例化时才会自行获取连接。

因此,如果它不适用于特定的表,这很可能是因为它已经被实例化并获取了默认连接(表注册表只为每个别名实例化一个表类)。

因此,要么确保之后正在实例化表,如果需要在请求后期创建别名,则可能需要清除(TableRegistry::clear())/从注册表中删除TableRegistry::remove()循环(但是可能会导致其他问题,因为您可能会松动可能应用的动态配置),或者手动设置所涉及的表的连接:

\Cake\Datasource\ConnectionManager::alias('database', 'default');
$connection = \Cake\Datasource\ConnectionManager::get('default');

$this->{$modelName}->setConnection($connection); // connection() before CakePHP 3.4

以更自动化的方式动态应用连接

如果您需要在多个或所有表格中使用此功能,或者您只是想从控制器转移责任(它很可能不应过度参与配置模型层),那么可能需要调度创建别名时的事件,使用基表类或侦听事件的行为,甚至可能使用"服务"知道表并相应地更新表连接。

\Cake\Datasource\ConnectionManager::alias('database', 'default');
$connection = \Cake\Datasource\ConnectionManager::get('default');

$event = new \Cake\Event\Event('Connection.aliased', $connection, ['source' => 'default']);
\Cake\Event\EventManager::instance()->dispatch($event);

例如,在表格中,您可以执行类似的操作,在表格配置为使用已设置别名的连接(即defaultConnectionName() === 'default'时)应用新连接,然后选择新连接:

\Cake\Event\EventManager::instance()->on(
    'Connection.aliased',
    function (\Cake\Event\Event $event) {
        // data() before CakePHP 3.4
        if ($event->getData('source') === static::defaultConnectionName()) {
            $this->setConnection($event->getSubject()); // subject() before CakePHP 3.4
        }
    }
);

另见

答案 1 :(得分:0)

我基于会话变量构建了一个具有动态连接的示例项目。 我希望有人觉得它有用: https://github.com/jszoja/cakephp3-multidb

我在那里记录了。