Dynamische Datenbankverbindung symfony2

Mein symfony2-Projekt hat eine Hauptdatenbank und viele untergeordnete Datenbanken. Jede untergeordnete Datenbank wird für jeden Benutzer erstellt, die Datenbankanmeldeinformationen werden in der Hauptdatenbank gespeichert. Wenn sich der Benutzer anmeldet, werden die benutzerspezifischen Datenbankanmeldeinformationen aus der Hauptdatenbank abgerufen, und die Verbindung zur untergeordneten Datenbank sollte idealerweise hergestellt werden. Ich habe gleich gegoogelt und bin auf eine Reihe von Lösungen gestoßen und habe schließlich Folgendes getan:

#config.yml

doctrine:
dbal:
    default_connection:       default
    connections:
        default:
            dbname:           maindb
            user:             root
            password:         null
            host:             localhost
        dynamic_conn:
            dbname:           ~
            user:             ~
            password:         ~
            host:             localhost
orm:
    default_entity_manager:   default
    entity_managers:
        default:
            connection:       default
            auto_mapping:     true
        dynamic_em:
            connection:       dynamic_conn
            auto_mapping:     true

Ich habe eine Standardverbindung für die Verbindung zur Hauptdatenbank und eine leere Verbindung für die untergeordnete Datenbank erstellt. Ebenso habe ich Entitätsmanager erstellt. Dann habe ich einen Standard-Ereignis-Listener erstellt und den folgenden Code zum 'onKernelRequest' hinzugefügt:

public function onKernelRequest(GetResponseEvent $event) //works like preDispatch in Zend
{
    //code to get db credentials from master database and stored in varaiables
    ....
    $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_em');
    ....
}

Der obige Code legt die Parameter der untergeordneten Datenbank fest und setzt den Entitätsmanager dynamic_em zurück.

Wenn ich das Folgende in einem Controller mache, funktioniert es einwandfrei und die Daten werden aus der untergeordneten Datenbank abgerufen.

$getblog= $em->getRepository('BloggerBlogBundle:Blog')->findById($id); //uses doctrine

Wenn ich jedoch den Sicherheitskontext aus dem folgenden Code verwende, wird die Fehlermeldung "KEINE DATENBANK AUSGEWÄHLT" angezeigt.

$securityContext = $this->container->get('security.context');
$loggedinUserid = $securityContext->getToken()->getUser()->getId();

Wie kann ich die Datenbankverbindung dynamisch einstellen und auch den Sicherheitskontext verwenden?

AKTUALISIEREN:-

Nachdem ich viel Zeit damit verbracht hatte, mich auszuprobieren und zu googeln, wurde mir klar, dass dies der Fall warsecurity.context wird vor der Ausführung von gesetztonKernelRequest. Nun ist die FrageWie die Datenbankverbindungsdetails in den security.context einzufügen, undwoher Einspritzen?

Wir müssen einen Punkt erreichen, an dem der DBAL- und Sicherheitskontext festgelegt und das Sicherheitstoken erstellt wird, und wir können die Details der Datenbankverbindung bearbeiten.

Daher habe ich, wie die Person im folgenden Link sagte, Änderungen an meinem Code vorgenommen, da dies genau das ist, was ich tun möchte.http://forum.symfony-project.org/viewtopic.php?t=37398&p=124413

So kann ich meinem Projekt den folgenden Code hinzufügen:

#config.yml //remains unchanged, similar to above code

Ein Compiler-Pass wird wie folgt erstellt:

// src/Blogger/BlogBundle/BloggerBlogBundle.php
namespace Blogger\BlogBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;

use Blogger\BlogBundle\DependencyInjection\Compiler\CustomCompilerPass;

class BloggerBlogBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $container->addCompilerPass(new CustomCompilerPass());
    }
}

Der Compiler-Pass lautet wie folgt:

# src/Blogger/BlogBundle/DependencyInjection/Compiler/CustomCompilerPass.php

class CustomCompilerPassimplements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $connection_service = 'doctrine.dbal.dynamic_conn_connection';
        if ($container->hasDefinition($connection_service))
        {
            $def = $container->getDefinition($connection_service);
            $args = $def->getArguments();
            $args[0]['driverClass'] = 'Blogger\BlogBundle\UserDependentMySqlDriver';
            $args[0]['driverOptions'][] = array(new Reference('security.context'));
            $def->replaceArgument(0, $args[0]);
        }
   }
}

Der Fahrerklassencode lautet wie folgt:

# src/Blogger/BlogBundle/UserDependentMySqlDriver.php

use Doctrine\DBAL\Driver\PDOMySql\Driver;

class UserDependentMySqlDriver extends Driver
{    
    public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
    {
        $dbname = .....  //store database name in variable
        $params['dbname'] = $dbname;
        return parent::connect($params, $username, $password, array());
    }
}

Der obige Code wurde meinem Projekt hinzugefügt, und ich gehe davon aus, dass dies die eigentliche Lösung für mein Problem ist.

Aber jetzt bekomme ich folgenden Fehler:

ServiceCircularReferenceException: Zirkelverweis für Dienst "security.context" erkannt, Pfad: "profiler_listener -> profiler -> security.context -> security.authentication.manager -> fos_user.user_provider.username_email -> fos_user.user_manager -> doctrine.orm. dynamic_manager_entity_manager -> doctrine.dbal.dynamic_conn_connection ".

Wie kann ich meinen Code zum Laufen bringen? Ich wette, dass ich hier etwas falsch mache und würde mich über Hinweise und Hilfe freuen.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage