Symfony 2 : birden çok dinamik ve veritabanı bağlantısı
Yeni SF2 oldum ve tek BİR yerde toplayıp severals veritabanı bağlantıları yönetmek nasıl merak ediyordum. Şu an için bu çözüm ince işleri - - var ama eğer bunu yapmak için doğru yol olduğunu bilmiyorum....
myBundle\Kaynak\config\config.yml :
doctrine:
dbal:
default_connection: default
connections:
default:
dbname: SERVER
user: root
password: null
host: localhost
client:
dbname: CLIENT_134
user: root
password: null
host: localhost
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
MyBundle: ~
client:
connection: client
mappings:
MyBundle: ~
Ve sonra, BD birine ya da geçmek için, ben yapmak :
$O_ressource= $this->get('doctrine')->getEntityManager('client');
$O_ressource= $this->get('doctrine')->getEntityManager('default');
Çocuklar, bu yönetmek için iyi bir yol olduğunu düşünüyor musunuz?
Ve ikinci sorum ise :
nasıl dinamik veritabanı bağlantısı kurmak için? Benim sistem 100 veritabanları var ve hepsi benim config bunları yapamam.dosya yml. Anında veritabanı değiştirmek mümkün olmak istiyorum.
Yardım için teşekkürler!
CEVAP
Eğer ConnectionFactory, olay kullanırsanız abone bağlantı bağlı, örneğin stofDoctrineExtensions çalışmayı durdurur.
Burada benim bir yöntemdir. ConnectionFactory ile bağlantı boş ve EntityManager var gibi. Çalışırken sadece Yansımaların bağlantı ayarlarınızı değiştirin. SF çalışır 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)
}
}
GÜNCELLEME:
Doktrin 2.2 / 2.3 sf (relection olmadan), php5 için oluşturulmuş zarif bir çözüm.4 (seviyorum yeni dizi başlatıcı :D) Doktrin özelliği bağlantı sarıcı adlı http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/portability.html bakın kullanabiliriz
Bu örnek, geçici depolama bağlantı ayrıntıları için oturum hizmeti kullanın.
İlk başta Özel bağlantı sarıcı oluşturmak için var:
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 [zulus@w3des.net]
*/
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;
}
}
}
Bir sonraki Doktrini yapılandırmanızı kaydetmek:
…
connections:
dynamic:
driver: Útabase_driver%
host: Útabase_host%
port: Útabase_port%
dbname: 'empty_database'
charset: UTF8
wrapper_class: 'w3des\DoctrineBundle\Connection\ConnectionWrapper'
Ve bizim ConnectionWrapper düzgün kayıtlı. Şimdi oturum enjeksiyon.
İlk özel CompilerPass sınıf oluşturun:
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')
]);
}
}
Ve biz *Paket sınıfta yeni derleyici bizim sınıf kayıt:
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new ConnectionCompilerPass());
}
Ve tüm bu!
Bağlantı oturum özelliklerine göre talep üzerine oluşturulur.
Veritabanı geçiş yapmak için, sadece kullanmak:
$this->get('doctrine.dbal.dynamic_connection')->forceSwitch($dbname, $dbuser, $dbpass);
Avantajları
- Daha fazla yansıması
- Talep oluÅŸturma
- Zarif ve güçlü
Dezavantajları
- Varlık yöneticisi temizleme Elle veya bu iş için özel Doktrini olay oluşturun
- Çok fazla kod

Birden fazla tabloya İnsert MySQL? (Ve...
Bir SQLite veritabanı aynı anda birden...
Django kalıcı veritabanı bağlantısı...
Burada birden fazla veritabanı motorla...
Postgresql: daha iyi 1 ÅŸema, her bir y...