由于各种原因(安全性等)我有一个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中可能有一种更好的方法可以做到这一点,我不知道,只要它有效并且不是一种不可维护的黑客,我愿意尝试任何东西。
谢谢。