zf2动态数据库连接(带参数)

时间:2014-07-06 10:48:29

标签: php zend-framework zend-framework2



我正在尝试创建一个包含多个数据库的ZF2应用程序。基于用户,应该动态设置数据库。

现在我有以下内容:

database.local.php     

return array(
    'db' => array(
        'adapters' => array (
            'master_db' => array(
                'driver'         => 'Pdo',
                'dsn'            => 'mysql:dbname=master_db;host=localhost',
                'driver_options' => array(
                    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
                ),
                'username'       => 'USERNAME',
                'password'       => 'PASSWORD'
            ),
            'tentant_db' => array(
                'driver'         => 'Pdo',
                'dsn'            => 'mysql:dbname=tenant_db;host=localhost',
                'driver_options' => array(
                    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
                ),
                'username'       => 'USERNAME',
                'password'       => 'PASSWORD'
            ),
        )
    ),
    'service_manager' => array(
        'abstract_factories' => array(
                'Zend\Db\Adapter\AdapterAbstractServiceFactory',
        )
    ),
);

出于测试目的,我创建了一个表单,其中包含一个获取某些数据并将其放入选择框的方法。获取数据库连接的代码显示在下面的代码中。

MyController.php(在某些模块中)

//... some code
public function someAction(){

        $dbAdapter = $this->getServiceLocator()->get('tentant_db');
        $form = new AddEolConnectorForm($dbAdapter);

        $viewModel = new ViewModel(array(
                                'form' => $form
                            ));
        return $viewModel;


    }

//... some more code

我的问题是,如何在控制器(或模块)中动态设置tentant_db适配器的dbname?

谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

配置合并事件是我相信的更新事件之一。当zend是mergin时,它会触发配置数组,这对于你所面临的问题是完美的,因为你可以动态地覆盖一些数组键。

public function onMergeConfig(ModuleEvent $e)
{
    $configListener = $e->getConfigListener();
    $config         = $configListener->getMergedConfig(false);

    // I'm actually not sure if you have the route match here otherwise you may have to
    // use some other method to retrieve the url.
    $match = $e->getRouteMatch();

    switch ($match) {
    case 'first-dependency':
       $config['db']['adapter'] => array(
          'driver'         => 'Pdo',
          'dsn'            => 'mysql:dbname=master_db;host=localhost',
          'driver_options' => array(
             PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
          ),
          'username'       => 'USERNAME',
          'password'       => 'PASSWORD',
        ),
    break;

    case 'second-dependency':
       $config['db']['adapter'] => array(
          'driver'         => 'Pdo',
          'dsn'            => 'mysql:dbname=tenant_db;host=localhost',
          'driver_options' => array(
             PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
          ),
          'username'       => 'USERNAME',
          'password'       => 'PASSWORD',
        ),
    break;

    // Pass the changed configuration back to the listener:
    $configListener->setMergedConfig($config);
}

答案 1 :(得分:0)

根据上述答案,我创建了以下内容:

<强> Module.php

class Module implements AutoloaderProviderInterface
{
  public function init(ModuleManager $moduleManager)
    {
        $events = $moduleManager->getEventManager();

        // Registering a listener at default priority, 1, which will trigger
        // after the ConfigListener merges config.
        $events->attach(ModuleEvent::EVENT_MERGE_CONFIG, array($this, 'onMergeConfig'));

    }

    public function onMergeConfig(ModuleEvent $e)
    {

        $db = $this->getTentantDb();
        $configListener = $e->getConfigListener();
        $config         = $configListener->getMergedConfig(false);

        $config['db']['adapters']['tenant_db']['dsn'] = 'mysql:dbname='. $db .';host=localhost';

        $configListener->setMergedConfig($config);
    }

    // Some more code

    public function getTenantDb(){

        $tenant_db = 'tenant_12345'
        return $tenant_db;
    }

}

我不知道它是否是最佳解决方案,但上述代码正常运行。我认为接下来的步骤应该是将代码放在一个通用模块中,以便我可以从我的所有模块中访问它。