我正在尝试创建一个具有多个数据库的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
谢谢你的帮助。
我相信配置合并事件是zend更新事件之一。它在zend合并配置数组时触发,这非常适合您面临的问题,因为您可以动态覆盖一些数组键。
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);
}
基于以上答案,我创建了以下内容:
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;
}
}
我不知道这是否是最好的解决方案,但上面的代码是有效的。我认为接下来的步骤应该是将代码放在一个通用模块或其他模块中,这样我就可以从我的所有模块中访问它。