1

我正在开发一个 Symfony2 站点,该站点将托管许多站点,并且每个站点都有自己的数据库。我已经实现了一项服务,它使用反射来更改“客户端”实体管理器上的连接参数(用户名、密码、数据库名)。在 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 使用的实体管理器?

4

1 回答 1

2

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

您可能会将其用于 getBundles(),或添加类似以下内容:

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

我还没有测试过,但它应该可以解决问题。boot() 是初始化容器的函数,因此您应该在容器初始化后立即进行切换,然后其他任何事情都有机会做任何事情。

于 2012-12-13T04:30:07.857 回答