Динамическое соединение с базой данных symfony2

Мой проект symfony2 имеет основную базу данных и множество дочерних баз данных. Каждая дочерняя база данных создается для каждого пользователя, учетные данные базы данных хранятся в основной базе данных. Когда пользователь входит в систему, учетные данные конкретной базы данных извлекаются из основной базы данных, и в идеале должно быть установлено дочернее соединение с базой данных. Я гуглил то же самое, нашел несколько решений и, наконец, сделал следующее:

#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

Я создал соединение по умолчанию для подключения к основной базе данных и пустое соединение для дочерней базы данных, аналогично я создал менеджеры сущностей. Затем я создал прослушиватель событий по умолчанию и добавил следующий код в onKernelRequest:

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');
    ....
}

Приведенный выше код устанавливает параметры дочерней базы данных и сбрасывает диспетчер сущностей dynamic_em.

Когда я делаю следующее в каком-то контроллере, он работает нормально, и данные извлекаются из дочерней базы данных.

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

Но когда я использую контекст безопасности, как показано в следующем коде, я получаю ошибку «NO DATABASE SELECTED».

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

Как я могу установить соединение с базой данных динамически и использовать контекст безопасности?

ОБНОВИТЬ:-

После большого количества времени, проведенного методом проб и ошибок, и погуглив, я понял, чтоsecurity.context устанавливается до исполненияonKernelRequest, Теперь вопроскак ввести информацию о соединении с базой данных в security.context игде вводить?

Нам нужно добраться до точки, где задан DBAL и контекст безопасности, и создан токен безопасности, и мы можем манипулировать деталями соединения с базой данных.

Следовательно, как сказал человек по следующей ссылке, я внес изменения в свой код, поскольку это именно то, что я хотел бы сделать.http://forum.symfony-project.org/viewtopic.php?t=37398&p=124413

Это оставляет мне следующий код добавить в мой проект:

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

Пропуск компилятора создается следующим образом:

// 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());
    }
}

Проход компилятора выглядит следующим образом:

# 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]);
        }
   }
}

Код класса драйвера выглядит следующим образом:

# 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());
    }
}

Приведенный выше код был добавлен в мой проект, и я предполагаю, что это реальное решение моей проблемы.

Но теперь я получаю следующую ошибку:

ServiceCircularReferenceException: обнаружена циклическая ссылка для службы "security.context", путь: "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 ".

Как я могу заставить мой код работать? Могу поспорить, что я делаю что-то не так, и я был бы признателен за любые советы и помощь.

Ответы на вопрос(3)

Ваш ответ на вопрос