Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 - Dynamic Doctrine Database Connections at Runtime

I am looking for a good solution to on-the-fly connection of databases within Symfony utilizing Doctrine for entity management.

The scenario I have is that all inbound users to our service will be visiting *.website.com addresses, like client1.website.com.

We would like to use one Doctrine entity for the Client table to then look up their database credentials based on the URL of their account on the fly.

So far I have found the following topics here on stackoverflow that discuss dynamically changing the database credentials--but no clear workable solutions.

I'd like to propose collaborating to put together a working solution, and I'll put together a blog/tutorial post for other folks looking to modify database connection parameters within Symfony.

Here are some related posts:

Dynamic database connection symfony2

Symfony2, Dynamic DB Connection/Early override of Doctrine Service

Thanks!

like image 755
Scott R. Avatar asked Dec 27 '13 18:12

Scott R.


2 Answers

If $em is existing entity manager and you want to reuse it's configuration, you can use this:

$conn = array(
    'driver'   => 'pdo_mysql',
    'user'     => 'root',
    'password' => '',
    'dbname'   => 'foo'
);

$new = \Doctrine\ORM\EntityManager::create(
    $conn,
    $em->getConfiguration(),
    $em->getEventManager()
);
like image 168
Michał Pipa Avatar answered Oct 24 '22 03:10

Michał Pipa


I needed to do something similar - runtime discovery of an available database server. I did it by overriding the doctrine.dbal.connection_factory.class parameter and substituting my own derivation of the Doctrine bundle's ConnectionFactory class

My services.yml provides the parameter, pointing at my custom class

parameters:
     doctrine.dbal.connection_factory.class: Path\To\Class\CustomConnectionFactory

Then fill in your discovery logic in Path\To\Class\CustomConnectionFactory.php

<?php

namespace Path\To\Class;

use Doctrine\Bundle\DoctrineBundle\ConnectionFactory;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;

class CustomConnectionFactory extends ConnectionFactory 
{

    public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = array())
    {
        // Discover and override $params array here.
        // A real-world example might obtain them from zookeeper,
        // consul or etcd for example. You'll probably want to cache
        // anything you obtain from such a service too.

        $params['driver'] = 'pdo_mysql';
        $params['host'] = '10.1.2.3';
        $params['port'] = 3306;
        $params['dbname'] = 'foo';
        $params['user'] = 'myuser';
        $params['password'] = 'mypass';

        //continue with regular connection creation using new params
        return parent::createConnection($params, $config, $eventManager,$mappingTypes);
    }

}

Note also that Symfony 3.2 features the ability to use environment variables in container configurations, and to use their values on-demand (rather than fixing them when the container is compiled). See the blog announcement for more details.

like image 20
Paul Dixon Avatar answered Oct 24 '22 05:10

Paul Dixon