2015-03-25 56 views
1

我已经在symfony2中实现了一个连接包装器,以根据子域连接到数据库。我也跟着上的问题的说明Symfony 2 : multiple and dynamic database connectionSymfony连接包装

它工作正常,但是当我尝试更新架构,symfony的是选择数据库(dinamic_database)的名字我的配置文件,而不是数据库的名称(数据库1)在我在Session中。

问题是类Doctrine \ DBALConnection中的私有属性$ params的值是在构造函数中创建的,我需要在我的覆盖连接方法中进行更改,但是由于没有任何方法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(); 
    } 
} 

} 

回答

0

我终于解决了这个问题,但不知道这是否是我重写的连接方法的构造方法在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; 
}