Multiple Doctrine connections

First of all, a little introducation of myself. My name is Christian Eikermann and I’m 22 years old and working as a Software Developer at Turtle Entertainment for more than 4 years.

Now, lets start with the topic..
It is a little bit hard to implemente mutliple connections with Doctrine in Symfony 1.x. We have spend some hours to find out how it could work. Finally, we found a good solution and wrote down a little tutorial, how you can use mutliple Doctrine connections for models.

Goal:
We want to store specific models in a seperated database and additional to have a decoupled Symfony plugin for it.

1. Bind connections to models

Frist we have to bind some models to a seperated connection, that is quite easy with Doctrine. Just add the “connection” key to your schema.yml in the model, that you want to bind to a seperated connection. The value of this key is the internal database name. For example:

1
2
3
4
5
ModelA:
connection: connection_b
columns:
foo: { type: integer, notnull: true }
bar: { type: integer, notnull: true }

Now you can rebuild your models and Doctrine will automatically adding the connection binding in the base model class file like:

1
2
// Connection Component Binding
Doctrine_Manager::getInstance()->bindComponent('ModelA', 'connection_b');

2. Evaluate database.yml in plugins

The next step is to evaluate the database.yml from your plugin config folder. Because Symfony doesn’t evaluate the database.yml file in each plugin config folder, it evaluates the database.yml from the root config folder only!

To solve this problem we have to evalute the database.yml manually. We need a initialized sfContext and sfDatabaseManager, so we connect to the “context.load_factories” event. The listener should run like the following code:

1
2
3
4
5
$configHandler = new sfDatabaseConfigHandler();
$databases = $configHandler->evaluate(array($this->getRootDir() . '/config/databases.yml'));

$databaseManager = $event->getSubject()->getDatabaseManager();
foreach ($databases as $name => $database) $databaseManager->setDatabase($name, $database);

Note: Doctrine sets the latest added connection always as the default connection! Maybe you have to save the current connection before you add  new database connection with:

1
$currentConnection = Doctrine_Manager::getInstance()->getCurrentConnection()->getName();

And restore it after you set your new database connection with:

1
Doctrine_Manager::getInstance()->setCurrentConnection($currentConnection);

3. Loading models

If you are using now the ModelATable to retrieve some models out of your database, Doctrine uses always the default connection. The problem is, that Symfony is not loading the base model files when you are using the table instance. So the connection binding, as described in step 1, is not done and the model “ModelA” is not bound to the seperated connection.

You can simple autoloading your specific models from the plugin with:

1
2
Doctrine_Core::loadModels($this->configuration->getRootDir() . '/lib/model/doctrine/' . $this->getName());
Doctrine_Core::loadModels($this->getRootDir() . '/lib/model');

The problem is also described in two bug tickets of Symfony and doctrine:
http://www.doctrine-project.org/jira/browse/DC-740
http://trac.symfony-project.org/ticket/7689

Now the table is using the right connection and you can start to work with your models ;)

 

 

Author: Christian Eikermann

Tags: ,

  • http://www.gasometro.com.ar/profile/steaph Zoe

    I like this post, enjoyed this one appreciate it for putting up.