matyas matyas - 1 year ago 62
PHP Question

Is it possible to use two diffrent document managers with different databases for the same bundle in Symfony?

My goal is to have two different document managers connected to different databases that share the same database models.

I have heavily changed my database model and I would like to write a custom migration script that retrieves objects from the old model reads its values and then creates a new object on the new schema with the information of the old object.

I have found a related stackoverflow question here:
Working with two entity managers in the same bundle in Symfony2

Howewer, this solution suggests to use different prefixes for each database and it stores the classes for the data model in different folders:

default_connection: default
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
driver: %database_sqlite_driver%
host: ~
port: ~
dbname: %database_sqlite_shop_name%
path: %database_sqlite_shop_name%
user: ~
password: ~
charset: UTF8

auto_generate_proxy_classes: %kernel.debug%
default_entity_manager: default
connection: default
# you must specify the type
type: "annotation"
# The directory for entity (relative to bundle path)
dir: "Entity/FirstDb"
#the prefix
prefix: "Your\Bundle\Entity\FirstDb"
connection: second
type: "annotation"
#here the second path where entity for the connection stand
dir: "Entity/SecondDb"
#the prefix
prefix: "Your\Bundle\Entity\SecondDb"

I would really just like to have two different document manager objects that share the same models in the same folder but are connected to diffrent databases. Is this possible?

Answer Source

I found out that it is indeed possible to be connected to different databases in the same Symfony Bundle. This answer led me to a possible solution:

class: %acme.dynamic_doctrine_connection.class%
    - [setDoctrineConnection, @doctrine.dbal.default_connection]]


namespace Acme\Bundle\AppBundle;

use Doctrine\DBAL\Connection;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Exception;

class DynamicDoctrineConnection
     * @var Connection
    private $connection;

     * Sets the DB Name prefix to use when selecting the database to connect to
     * @param  Connection       $connection
     * @return SiteDbConnection $this
    public function setDoctrineConnection(Connection $connection)
        $this->connection = $connection;

        return $this;

    public function setUpAppConnection()
        if ($this->request->attributes->has('appId')) {
            $connection = $this->connection;
            $params     = $this->connection->getParams();

            // we also check if the current connection needs to be closed based on various things
            // have left that part in for information here
            // $appId changed from that in the connection?
            // if ($connection->isConnected()) {
            //     $connection->close();
            // }

            // Set default DB connection using appId
            //$params['host']   = $someHost;
            $params['dbname'] = 'Acme_App'.$this->request->attributes->get('appId');

            // Set up the parameters for the parent
                $params, $connection->getDriver(), $connection->getConfiguration(),

            try {
            } catch (Exception $e) {
                // log and handle exception

        return $this;

With the solution above one can write a service that can be called to change the database that the current entity manager is connected to to a different database.

Unfortunately the solution above only works for the PDO driver (Mysql). Since our technology stack includes mongodb and we use the doctrine-mongodb bundle I had to look for a differnt solution.

The doctrine-mongodb documentation has a section about setting up a custom document manager here:

I was unable to get the right doctrine-mongodb odm document mappings to work with the instructions in the doc and therefore the only solution for me was to create a simple PHP mongoclient connection:

$mongo = new \Mongo('mongodb://localhost:27017');
$legacyDbDocumentMangager = $mongo->selectDB('backed_up_prod_db');
$legacyUserCollection = $legacyDbDocumentMangager->selectCollection('User');
$user = $legacyUserCollection->findOne(array('email' => ''));

The only differnce between this simple php mongodb driver and the doctrine-mongodb odm is that the results of the queries of this driver are associative arrays and the results of the doctrine-mongodb odm diver are objects.

I hope this information is useful to someone.