#php #zend-framework #zend-framework2
#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(
'ZendDbAdapterAdapterAbstractServiceFactory',
)
),
);
В целях тестирования я создал форму, в которой есть метод для извлечения некоторых данных и помещения их в поле выбора. Код для получения подключения к базе данных показан в коде ниже.
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
Мой вопрос в том, как я могу динамически задать dbname для адаптера tentant_db в моем контроллере (или модуле)?
Спасибо за вашу помощь.
Комментарии:
1. zf2.readthedocs.org/en/develop/tutorials/…
2. @cptnk Я не думаю, что понимаю, что вы пытаетесь сказать. Я довольно новичок в zf2. Не могли бы вы, пожалуйста, дать мне еще несколько указаний?
Ответ №1:
Событие слияния конфигурации, я полагаю, является одним из более новых событий 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);
}
Комментарии:
1. Я думаю, что нашел решение, основанное на вашем ответе. Спасибо!
Ответ №2:
Основываясь на приведенном выше ответе, я создал следующее:
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;
}
}
Я не знаю, лучшее ли это решение, но приведенный выше код работает. Я думаю, что следующими шагами должно быть помещение кода в универсальный модуль или что-то в этом роде, чтобы я мог получить к нему доступ из всех моих модулей.