在Symfony2中的每个请求之前动态设置Doctrine EntityManager连接

时间:2012-12-13 02:51:24

标签: php symfony doctrine-orm fosuserbundle

我正在开发一个将托管多个站点的Symfony2站点,每个站点都有自己的数据库。我已经实现了一个服务使用反射来更改'客户端'实体管理器上的连接参数(用户名,密码,dbname)。在FOSUserBundle调用其身份验证服务之前,我不确定如何触发此服务。我试图创建一个Symfony2 Request事件监听器,但这似乎不起作用:

class RequestListener {
    private $clientSiteContext;

    function __construct($clientSiteContext) {
        $this->clientSiteContext = $clientSiteContext;
    }

    public function onKernelRequest(GetResponseEvent $event) {
        if ($event->getRequestType() == HttpKernel::MASTER_REQUEST) {
            $this->clientSiteContext->resetClientEntityManager();
        }
    }
}

resetClientEntityManager()实现

public function resetClientEntityManager() {
    /** @var $doctrine \Doctrine\Bundle\DoctrineBundle\Registry */
    $doctrine = $this->container->get('doctrine');

    $dbConfig = $this->getConnectionParams();
    $dbalServiceName = sprintf('doctrine.dbal.%s_connection', 'client');
    $clientEmName = 'client';

    $connection = $this->container->get($dbalServiceName);
    $connection->close();

    $refConn = new \ReflectionObject($connection);
    $refParams = $refConn->getProperty('_params');
    $refParams->setAccessible('public');

    $params = $refParams->getValue($connection);
    $params['dbname'] = $dbConfig['dbname'];
    $params['user'] = $dbConfig['user'];
    $params['host'] = $dbConfig['host'];
    $params['password'] = $dbConfig['password'];
    $params['driver'] = $dbConfig['driver'];
    $params['charset'] = 'UTF8';

    $refParams->setAccessible('private');
    $refParams->setValue($connection, $params);

    $doctrine->resetEntityManager($clientEmName);
}

有人可以建议我如何让这个侦听器为每个页面请求调用一次,并且它会影响FOSUserBundle使用的实体管理器吗?

1 个答案:

答案 0 :(得分:2)

你必须在任何内核事件之前拥有它。可能最好的地方就是把它放在AppKernel(app/AppKernel.php)本身的某个地方。

你可以把它带到getBundles(),或添加类似的东西:

public function boot() {
    parent::boot();
    resetClientEntityManager();
}

我没有测试过,但它应该可以解决问题。 boot()是容器初始化的函数,所以你应该在容器初始化之后立即进行切换,之后其他任何东西都有可能做任何事情。