Соединитель Symfony

Я реализовал в symfony2 оболочку подключения для подключения к базе данных в зависимости от поддоменов. Я следовал инструкциям по вопросу Symfony 2: множественное и динамическое соединение с базой данных

Это работает нормально, но когда я пытаюсь обновить схему, symfony выбирает имя базы данных (dinamic_database), которое у меня есть в файле конфигурации, вместо имени базы данных (database1), которое я имею в сеансе.

Проблема заключается в том, что значение частного свойства $ params в классе Doctrine \ DBALConnection создается в конструкторе, и мне нужно изменить его в методе переопределения подключения, но я не могу изменить это свойство, потому что у меня нет методов setParams ()

config.yml

doctrine:
dbal:
default_connection: default
connections:
default:
driver:   "%database_driver%"host:     "%database_host%"port:     "%database_port%"dbname:   "%database_name%"user:     "%database_user%"password: "%database_password%"charset:  UTF8
cliente:
wrapper_class: 'Em\Bundle\AppBundle\Connection\ConnectionWrapper'
driver:   "%database_driver%"host:     "%database_host%"port:     "%database_port%"dbname:   'dinamic_database'
user:     "%database_user%"password: "%database_password%"charset:  UTF8
orm:
auto_generate_proxy_classes: %kernel.debug%
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
EmAdminBundle: ~
EmBackOfficeBundle: ~
EmContabilidadBundle: ~

filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true
dql:
string_functions:
MONTH: DoctrineExtensions\Query\Mysql\Month
YEAR: DoctrineExtensions\Query\Mysql\Year
cliente:
connection: cliente
mappings:
EmAppBundle: ~

Соединительная оболочка

class ConnectionWrapper extends Connection
{

const SESSION_ACTIVE_DYNAMIC_CONN = 'active_dynamic_conn';

/**
* @var Session
*/
private $session;

/**
* @var bool
*/
private $_isConnected = false;

/**
* @var
*/
private $defaultDatabaseName;

/**
* @param Session $sess
*/
public function setSession(Session $sess)
{
$this->session = $sess;

}/**
* @param Session $sess
*/
public function setDefaultDatabaseName($defaultDatabaseName)
{
$this->defaultDatabaseName = $defaultDatabaseName;
}

public function forceSwitch($dbName)
{

if ($this->session->has(self::SESSION_ACTIVE_DYNAMIC_CONN)) {
$current = $this->session->get(self::SESSION_ACTIVE_DYNAMIC_CONN);
if ($current[0] === $dbName) {
return;
}
}

$this->session->set(self::SESSION_ACTIVE_DYNAMIC_CONN, [
$dbName
]);

if ($this->isConnected()) {
$this->close();
}
}

public function forceDefault()
{
$this->forceSwitch($this->defaultDatabaseName);
}

/**
* {@inheritDoc}
*/
public function connect()
{

if (!$this->session->has(self::SESSION_ACTIVE_DYNAMIC_CONN)) {
throw new \InvalidArgumentException('You have to inject into valid context first');
}
if ($this->isConnected()) {
return true;
}

$driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array();

$params = $this->getParams();
$realParams = $this->session->get(self::SESSION_ACTIVE_DYNAMIC_CONN);
$params['dbname'] = $realParams[0];

// $params['dbname'] is "database1"
$this->_conn = $this->_driver->connect($params, $params['user'], $params['password'], $driverOptions);

$paramsAfterConection = $this->getParams();
// $paramsAfterConection['dbname'] is "dinamic_database"
if ($this->_eventManager->hasListeners(Events::postConnect)) {
$eventArgs = new ConnectionEventArgs($this);
$this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
}

$this->_isConnected = true;

return true;
}/**
* {@inheritDoc}
*/
public function isConnected()
{
return $this->_isConnected;
}

/**
* {@inheritDoc}
*/
public function close()
{
if ($this->isConnected()) {
parent::close();
$this->_isConnected = false;
}
}
}

Менеджер баз данных

class DatabaseManager
{
/**
* @var EntityManager
*/
private $emCliente;

/**
* @var ConnectionWrapper
*/
private $connection;

public function __construct(EntityManager $emCliente, ConnectionWrapper $connection)
{
$this->emCliente =  $emCliente;
$this->connection = $connection;
}

public function createDatabaseApp(AppEvent $event) {
$app = $event->getApp();
$database = $app->getDatabaseName();
$this->connection->getSchemaManager()->createDatabase($database);
$this->connection->forceSwitch($database);
$metadatas = $this->emCliente->getMetadataFactory()->getAllMetadata();
$tool = new SchemaTool($this->emCliente);
$tool->createSchema($metadatas);
$this->connection->forceDefault();

}

public function deleteDatabaseApp(AppEvent $event)
{
$app = $event->getApp();
$database = $app->getDatabaseName();
if(in_array($database, $this->connection->getSchemaManager()->listDatabases())){
$this->connection->getSchemaManager()->dropDatabase($database);
}
}

public function updateSchema(App $app)
{
$database = $app->getDatabaseName();
if(in_array($database, $this->connection->getSchemaManager()->listDatabases())){
$this->connection->forceSwitch($database);
$metadatas = $this->emCliente->getMetadataFactory()->getAllMetadata();
$tool = new SchemaTool($this->emCliente);

$sm = $this->connection->getSchemaManager();

$fromSchema = $sm->createSchema();
//fromSchema is trying to get information from dinamic_database instead of database1

$toSchema = $tool->getSchemaFromMetadata($metadatas);

$comparator = new Comparator();
$schemaDiff = $comparator->compare($fromSchema, $toSchema);
$sqls = $schemaDiff->toSql($this->connection->getDatabasePlatform());

}
}
public function dropSchema(App $app)
{
$database = $app->getDatabaseName();
if(in_array($database, $this->connection->getSchemaManager()->listDatabases())){
$this->connection->forceSwitch($database);
$this->connection->executeQuery('SET FOREIGN_KEY_CHECKS = 0');
$metadatas = $this->emCliente->getMetadataFactory()->getAllMetadata();
$tool = new SchemaTool($this->emCliente);
$tool->dropSchema($metadatas);
$this->connection->executeQuery('SET FOREIGN_KEY_CHECKS = 1');
$this->connection->forceDefault();
}
}

}

1

Решение

Я наконец решил проблему, но не знаю, если это лучший способ

Я переопределяю метод конструктора в методе подключения в ConnectionWrapper:

public function connect()
{

if (!$this->session->has(self::SESSION_ACTIVE_DYNAMIC_CONN)) {
throw new \InvalidArgumentException('You have to inject into valid context first');
}
if ($this->isConnected()) {
return true;
}

$driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array();

$params = $this->getParams();
$realParams = $this->session->get(self::SESSION_ACTIVE_DYNAMIC_CONN);
$params['dbname'] = $realParams[0];

//overrride constructor in parent class Connection to set new parameter dbname
parent::__construct($params, $this->_driver, $this->_config,$this->_eventManager);

$this->_conn = $this->_driver->connect($params, $params['user'], $params['password'], $driverOptions);if ($this->_eventManager->hasListeners(Events::postConnect)) {
$eventArgs = new ConnectionEventArgs($this);
$this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
}

$this->_isConnected = true;

return true;
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]