Symfony 2 : birden çok dinamik ve veritabanı bağlantısı | Netgez.com
SORU
20 HAZÄ°RAN 2011, PAZARTESÄ°


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
15 ŞUBAT 2012, ÇARŞAMBA


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ı

  1. Daha fazla yansıması
  2. Talep oluÅŸturma
  3. Zarif ve güçlü

Dezavantajları

  1. Varlık yöneticisi temizleme Elle veya bu iş için özel Doktrini olay oluşturun
  2. Çok fazla kod

Bunu PaylaÅŸ:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • Brandon McCrary

    Brandon McCr

    15 Ocak 2012
  • JamesAtiPhone

    JamesAtiPhon

    16 EYLÃœL 2010
  • sWooZie

    sWooZie

    9 ÅžUBAT 2006