【问题标题】:CakePHP 3 dynamic database connectionCakePHP 3 动态数据库连接
【发布时间】:2018-01-21 22:46:41
【问题描述】:

在控制器中,我想更改我的默认数据库连接,以便我可以访问不同的数据库。以前可以的,我在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');

我创建了一个新的数据库连接,将其命名为“数据库”,并为该连接命名为默认连接,这样将使用该连接而不是默认连接。但是,当我打印时

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

它仍然提供默认连接。一个错误说该表不存在,确认我不在新连接的数据库中。

【问题讨论】:

    标签: php database cakephp database-connection config


    【解决方案1】:

    仅在表实例化时提取别名

    动态连接连接通常可以正常工作,但模型/表类仅在实例化时自行拾取一次连接。

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

    所以,要么确保表在之后被实例化,如果需要在请求周期的后期创建别名(但是可能会导致其他问题,因为您可能会丢失可能应用的动态配置),或手动设置相关表上的连接:

    \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
            }
        }
    );
    

    另见

    【讨论】:

    • 这完全有效,连接确实已经被实例化了。做你说的一切,让它工作。谢谢!
    【解决方案2】:

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

    我在那里记录了它。

    【讨论】:

    • 非常有用。帮助我实现了多租户应用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2019-03-26
    相关资源
    最近更新 更多