/** * Test multiple db resources specified in a local dbResources table * loop through each connection specified and request connection info * via the connection manager */ public function testLoopThroughDifferentDbResources() { $dbFactory = \Yii::$app->get('dbFactory'); $dbResources = DbResource::find()->orderBy('id')->all(); $counter = 1; foreach ($dbResources as $dbResource) { $counter++; $dbClient = $dbFactory->getConnection($dbResource->resourceName, true); $this->assertInstanceOf(Connection::className(), $dbClient); $this->assertEquals($dbResource->dbDsn, $dbClient->dsn); $this->assertEquals($counter, $dbFactory->getResourceCount()); // models want to make use of a dbClient connection so add an alias to it $this->assertTrue($dbFactory->addResourceAlias($dbResource->resourceName, 'dbClient')); // we should be able to get a connection $this->assertTrue($dbFactory->connectResource('dbClient')); $this->assertTrue($dbFactory->isResourceConnected('dbClient')); $this->assertInstanceOf('\\PDO', $dbClient->pdo); if ($dbResource->resourceName == 'dbClient1') { $this->assertRegExp('/dbTestClient1/', $dbClient->dsn); } else { $this->assertRegExp('/dbTestClient2/', $dbClient->dsn); } $customer = new Customer(); if ($dbResource->resourceName == 'dbClient1') { $this->assertTrue(!$customer->hasAttribute('extraField')); } else { // the customer table for CLIENT2 has an extra extraField attribute $this->assertTrue($customer->hasAttribute('extraField')); } $dbRemoteResource = ClientDbResource::find()->where(['resourceName' => 'dbRemote'])->one(); $dbParams = array('class' => $dbRemoteResource->dbClass, 'dsn' => $dbRemoteResource->dbDsn, 'username' => $dbRemoteResource->dbUser, 'password' => $dbRemoteResource->dbPass, 'charset' => $dbRemoteResource->dbCharset, 'tablePrefix' => $dbRemoteResource->dbPrefix, 'connect' => false, 'enableSchemaCache' => $dbClient->enableSchemaCache, 'schemaCacheDuration' => $dbClient->schemaCacheDuration, 'schemaCacheExclude' => array(), 'schemaCache' => $dbClient->schemaCache, 'enableQueryCache' => $dbClient->enableQueryCache, 'queryCacheDuration' => $dbClient->queryCacheDuration, 'queryCache' => $dbClient->queryCache, 'emulatePrepare' => NULL); $this->assertTrue($dbFactory->addResource('dbRemote', false, false, $dbParams)); $dbRemote = $dbFactory->getConnection('dbRemote'); $this->assertInstanceOf(Connection::className(), $dbRemote); $this->assertEquals($dbRemoteResource->dbDsn, $dbRemote->dsn); $this->assertEquals($counter + 1, $dbFactory->getResourceCount()); // we should be able to get a connection $this->assertTrue($dbFactory->connectResource('dbRemote')); $this->assertTrue($dbFactory->isResourceConnected('dbRemote')); $this->assertInstanceOf('\\PDO', $dbRemote->pdo); if ($dbResource->resourceName == 'dbClient1') { $this->assertRegExp('/dbTestRemote1/', $dbRemote->dsn); } else { $this->assertRegExp('/dbTestRemote2/', $dbRemote->dsn); } $robot = Robot::findOne(1); if ($dbResource->resourceName == 'dbClient1') { $this->assertTrue(!$robot->hasAttribute('extraField')); } else { // the robot table for CLIENT2s dbRemote connection has an extra extraField attribute $this->assertTrue($robot->hasAttribute('extraField')); } $this->assertTrue($dbFactory->removeResourceAlias('dbClient')); $this->assertTrue($dbFactory->removeResource('dbRemote')); } $this->assertTrue($dbFactory->removeAllResources()); $this->assertEquals(1, $dbFactory->getResourceCount()); $this->assertTrue($dbFactory->removeAllResources(true)); $this->assertEquals(0, $dbFactory->getResourceCount()); }
/** * Add a new resource and setup the DB connection * * @param string $resourceName * @param boolean $clientResource default to loading the resource from the clients resources table rather than the master resources table * @param boolean $checkServices check services for db connections that have not been registered via the connection manager (default true) * @param array|false $dbParams array of parameters for the connection, similar to what would be found in config (default false) * @return boolean success */ public function addResource($resourceName, $clientResource = false, $checkServices = true, $dbParams = false) { if ($checkServices) { if ($this->hasService($resourceName)) { /* @var Connection $connection */ $connection = $this->getService($resourceName); if ($connection) { $class = get_class($connection); $this->extendResourceArray($resourceName, $connection, $class); } } } $resourceNameCheck = $this->getResourceNameByAlias($resourceName); if ($resourceName && isset($this->resources['Resources'][$resourceNameCheck])) { // resource already exists return true; } elseif ($resourceName) { $dbResource = false; if ($dbParams && is_array($dbParams)) { // use the dbParams provided } elseif ($resourceName == 'dbClient') { /* * We need to load up the client DB connection and it is not defined as config * so we will get the details from the db.clients table */ $dbResource = $this->getService('client'); if ($dbResource && $dbResource instanceof Client) { // take some default values form the defaul connection (which would have come from config $connection = $this->getConnection(); } } elseif ($clientResource) { $client = $this->getService('client'); if ($client && $client instanceof Client) { $connection = $this->getClientConnection(true); if ($connection && $connection instanceof Connection) { try { $dbResource = ClientDbResource::find()->where(['resourceName' => $resourceName])->one(); } catch (YiiDbException $e) { throw new Exception('Unable to load client dbResources'); } } else { throw new Exception('No connections to client db available'); } } else { throw new Exception('No client service available'); } } else { $connection = $this->getConnection(); if ($connection && $connection instanceof Connection) { try { $dbResource = DbResource::find()->where(['resourceName' => $resourceName])->one(); } catch (YiiDbException $e) { throw new Exception('Unable to load dbResources'); } } else { throw new Exception('No connections to load dbResources'); } } if ($dbResource) { $dbParams = array('class' => $dbResource->dbClass, 'dsn' => $dbResource->dbDsn, 'username' => $dbResource->dbUser, 'password' => $dbResource->dbPass, 'charset' => $dbResource->dbCharset, 'tablePrefix' => $dbResource->dbPrefix, 'connect' => false, 'enableSchemaCache' => $connection->enableSchemaCache, 'schemaCacheDuration' => $connection->schemaCacheDuration, 'schemaCacheExclude' => array(), 'schemaCache' => $connection->schemaCache, 'enableQueryCache' => $connection->enableQueryCache, 'queryCacheDuration' => $connection->queryCacheDuration, 'queryCache' => $connection->queryCache, 'emulatePrepare' => NULL); } if ($dbParams) { if (isset($dbParams['password']) && substr($dbParams['password'], 0, 1) == '#') { $dbParams['password'] = $this->decrypt($dbParams['password']); } $connection = $this->setupConnection($dbParams); if ($connection) { $class = get_class($connection); $this->extendResourceArray($resourceName, $connection, $class, isset($dbParams['connect']) ? $dbParams['connect'] : false); // add resourceName to the service manager as well (setup as not shared) if ($this->hasService($resourceName)) { $this->setService($resourceName, null); } $this->setService($resourceName, $connection); return true; } } else { throw new Exception('Missing dbParams on addResource'); } } return false; }