यदि आप ConnectionFactory
का उपयोग करते हैं, तो कनेक्शन से जुड़े आपके ईवेंट ग्राहक काम करना बंद कर देंगे, उदाहरण के लिए stofDoctrineExtensions।
यहां मेरी विधि है। मेरे पास ConnectionFactory
के साथ खाली कनेक्शन और EntityManager है। काम करते समय मैं प्रतिबिंब द्वारा कनेक्शन कॉन्फ़िगरेशन को प्रतिस्थापित करता हूं। एस एफ 2.0.10 पर काम करता है;)
class YourService extends ContainerAware
{
public function switchDatabase($dbName, $dbUser, $dbPass)
{
$connection = $this->container->get(sprintf('doctrine.dbal.%s_connection', 'dynamic_conn'));
$connection->close();
$refConn = new \ReflectionObject($connection);
$refParams = $refConn->getProperty('_params');
$refParams->setAccessible('public'); //we have to change it for a moment
$params = $refParams->getValue($connection);
$params['dbname'] = $dbName;
$params['user'] = $dbUser;
$params['password'] = $dbPass;
$refParams->setAccessible('private');
$refParams->setValue($connection, $params);
$this->container->get('doctrine')->resetEntityManager('dynamic_manager'); // for sure (unless you like broken transactions)
}
}
अद्यतन:
सिद्धांत 2.2 के लिए अधिक सुरुचिपूर्ण समाधान/एस एफ 2.3 (relection के बिना), php5.4 (मैं नई सरणी प्रारंभकर्ता प्यार के लिए बनाया: डी) हम कनेक्शन रैपर नामक सिद्धांत सुविधा का उपयोग कर सकते हैं, http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/portability.html
यह उदाहरण अस्थायी भंडारण कनेक्शन विवरण के लिए सत्र सेवा का उपयोग करें।
namespace w3des\DoctrineBundle\Connection;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Session\Session;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Event\ConnectionEventArgs;
/*
* @author Dawid zulus Pakula [[email protected]]
*/
class ConnectionWrapper extends Connection
{
const SESSION_ACTIVE_DYNAMIC_CONN = 'active_dynamic_conn';
/**
* @var Session
*/
private $session;
/**
* @var bool
*/
private $_isConnected = false;
/**
* @param Session $sess
*/
public function setSession(Session $sess)
{
$this->session = $sess;
}
public function forceSwitch($dbName, $dbUser, $dbPassword)
{
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,
$dbUser,
$dbPass
]);
if ($this->isConnected()) {
$this->close();
}
}
/**
* {@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['user'] = $realParams[1];
$params['password'] = $realParams[2];
$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;
}
/**
* {@inheritDoc}
*/
public function isConnected()
{
return $this->_isConnected;
}
/**
* {@inheritDoc}
*/
public function close()
{
if ($this->isConnected()) {
parent::close();
$this->_isConnected = false;
}
}
}
अगला अपने सिद्धांत विन्यास में इसे पंजीकृत:
पहले तो हम विशेष कनेक्शन आवरण बनाने के लिए
…
connections:
dynamic:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: 'empty_database'
charset: UTF8
wrapper_class: 'w3des\DoctrineBundle\Connection\ConnectionWrapper'
और हमारे ConnectionWrapper ठीक से पंजीकृत है। अब सत्र इंजेक्शन।
पहले विशेष CompilerPass वर्ग बनाने के लिए:
namespace w3des\DoctrineBundle\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
class ConnectionCompilerPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$connection = $container
->getDefinition('doctrine.dbal.dynamic_connection')
->addMethodCall('setSession', [
new Reference('session')
]);
}
}
और हम * बंडल वर्ग में हमारे नए संकलक वर्ग रिकॉर्ड:
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new ConnectionCompilerPass());
}
और वह अपने सभी!
सत्र गुणों के आधार पर कनेक्शन मांग पर बनाया जाएगा।
डेटाबेस जाने के लिए, बस का उपयोग करें:
$this->get('doctrine.dbal.dynamic_connection')->forceSwitch($dbname, $dbuser, $dbpass);
लाभ
- कोई और अधिक प्रतिबिंब
- निर्माण की मांग पर
- सुरुचिपूर्ण और शक्तिशाली
नुकसान
- आप सफाई तो अपनी इकाई के प्रबंधक manualy के लिए, या इस
- के लिए विशेष सिद्धांत घटना बनाने के बहुत अधिक कोड
"गतिशील डेटाबेस कनेक्शन," आप अपने नियंत्रक से एक DBAL संबंध बनाने का अर्थ यह है द्वारा? – Problematic
हाँ, बिल्कुल! एक डेटाबेस से दूसरे डेटाबेस में बदलने में सक्षम हो, और इन डेटाबेस को config.yml फ़ाइल – Fish
में घोषित नहीं किया जा सकता है getEntityManager symfony2 –