Symfony2在运行时覆盖Doctrine DB凭据

时间:2015-11-04 16:47:09

标签: php symfony doctrine-orm doctrine

由于各种原因(安全性等)我有一个Symfony2应用程序,我想在其中指定多个数据库的凭据,但我不希望这些存储在磁盘上的任何位置。我不能将它们存储为系统变量,当然也不希望它们出现在Symfony Cache文件夹中。我想在运行时能够从另一个在Symfony之外运行的API获取我的数据库凭证(实际上超出了问题的范围)。执行所有这些操作的代码需要在Bundle中,因此我们也可以在其他应用程序中使用它(并且我被要求将其保存在一个包中)。

所以,这是我在config.yml中为示例数据库连接做的事情(可以有多个):

doctrine:
dbal:
    default_connection: default
    connections:
        default:
            driver:         %database_driver%
            dbname:         %database_name%
            charset:        UTF8
            server_version: 5.6

在parameters.yml中指定了驱动程序和dbname。

在我的主要services.yml文件中,我有以下内容:

app.doctrine_default_connection_factory:
    class: Vendor\Bundle\MyBundle\CustomConnectionFactory\DoctrineFactory
    arguments: [@doctrine.dbal.default_connection, @logger]
    scope: request
    tags:
        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

DoctrineFactory类按以下方式执行:

class DoctrineFactory  
{

    public function __construct(&$connection, $logger)
    {
        // Run some code to get credentials from elsewhere.
        // Update connection params.
        $params['user'] = $this->getUser();
        $params['password'] = $this->getPassword();
        $params['driverOptions'] = [
            \PDO::MYSQL_ATTR_SSL_CA => $this->getCaCert(),
            \PDO::MYSQL_ATTR_SSL_CERT => $this->getPublicCert(),
            \PDO::MYSQL_ATTR_SSL_KEY => $this->getPrivateKey()
        ];

        // If connected, close existing connection to the database.
        if ($connection->isConnected()) {
            $connection->close();
        }

        // Connect again with the new credentials.
        $connection->__construct(
            $params, $connection->getDriver(), $connection->getConfiguration(), $connection->getEventManager()
        );

        try {
            $connection->connect();
        } catch (Exception $e) {
            // log and handle exception
            $this->logger->error('Unable to connect to database: ' . $e->getMessage());
        }
    }

    public function onKernelRequest() {}
    // Other methods go here.

}

此代码在PHP 5.5之前运行良好,但由于Symfony解析服务请求并调用DoctrineFactory类的方式,它开始从PHP 5.5+中抛出异常。简而言之,当Symfony解析services.yml来编写PHP(在app / cache / appXXXXContainer.php中)时,它会使用以下代码实例化DoctrineFactory类:

new Vendor\Bundle\MyBundle\CustomConnectionFactory\DoctrineFactory($this->get('doctrine.dbal.default_connection'), $this->get('logger'));

提示PHP抛出异常,因为不能使用方法通过引用传递变量。

如果在DoctrineFactory类中,$ connection变量未通过引用传递,则一旦该方法完成执行,Symfony就不会使用新凭据(我已经尝试返回更新的$ connection变量),因此对于指定的任何代码在具有数据库查询的此类的其他包或外部,Doctrine没有凭据。出于这个原因,我不得不通过引用传递$ connection。

有没有办法让我在捆绑包中在运行时覆盖config.yml中指定的数据库凭据而不通过引用使用此变量?

在Symfony中可能有一种更好的方法可以做到这一点,我不知道,只要它有效并且不是一种不可维护的黑客,我愿意尝试任何东西。

谢谢。

0 个答案:

没有答案
相关问题