使用多个时自动装配特定的 DBAL 连接
Autowire specific DBAL connection when using multiple of them
我正在使用 Doctrine 2,其中我有多个 DBAL 连接。我在 ORM 中也有多个 EntityManagers。
我需要能够以某种方式将特定的 DBAL 连接自动连接到其他 Symfony 3 服务中。
我可以使用 EntityManagerDecorator 自动装配任何 EntitiyManager,但不知道如何对连接做同样的事情。我能够从 EntityManager 获得连接,但我不认为这是可行的方法。
每个 DBAL 连接始终可以在具有以下标识符的服务容器中访问:
doctrine.dbal.[name]_connection
其中 [name]
是连接名称
我遇到了同样的问题并更准确地测试了它有效的方法和原因。
使用代理进行许多 DBAL 连接
编辑:
我做了一些代理摘要class。现在我的每个连接 class 都继承自该代理。它工作正常:)
<?php
#src/AppBundle/Connections/ConnectionProxy.php
namespace AppBundle\Connections;
use Doctrine\DBAL\Connection;
abstract class ConnectionProxy
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
public function __call($method, $arguments)
{
if (is_callable(array($this->connection, $method))) {
return call_user_func_array(array($this->connection, $method), $arguments);
} else {
return new \Exception("Call to undefined method '{$method}'");
}
}
}
我的连接默认值class:
<?php
#src/AppBundle/Connections/ConnectionDefault.php
namespace AppBundle\Connections;
class ConnectionDefault extends ConnectionProxy
{
}
第二个连接:
<?php
namespace AppBundle\Connections;
class ConnectionSecond extends ConnectionProxy
{
}
然后我为所有连接(2 个连接)手动添加到我的服务文件中:
AppBundle\Connections\ConnectionDefault:
public: true
class: AppBundle\Connections\ConnectionDefault
arguments: ['@doctrine.dbal.default_connection']
AppBundle\Connections\ConnectionSecond:
public: true
class: AppBundle\Connections\ConnectionSecond
arguments: ['@doctrine.dbal.second_connection']
然后当我使用它们的类型时我的连接会自动自动装配
class SaveEvent
{
/** @var Connection */
private $connection;
public function __construct(ConnectionDefault $connection)
{
$this->connection = $connection;
}
.....
为每个服务注入连接
最简单的选项 - 但需要单独创建每个服务并注入连接名称 - 这意味着在您的服务文件中手动连接参数**(app/config/services.yml)例如
AppBundle\Classes\SaveEvent:
public: true
arguments:
- '@doctrine.dbal.[connection_name]_connection'
其中 connection_name 是您的连接名称。
在下面的示例中,我们在 config.yml 中有两个连接,此值可以是“default”或“database2”:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_sqlite
charset: UTF8
path: '%database_path%'
database2:
driver: pdo_sqlite
charset: UTF8
path: '%database_path%'
仅适用于一个 DBAL 连接
当我们只有一个连接时,DBAL 连接的自动装配工作正常。如果我只保留默认连接(从 config.yml 中删除连接数据库 2)并在 app/config/services.yml:
中添加一些要自动连接的路径
AppBundle\Classes\:
resource: '../../src/AppBundle/Classes'
public: true
如果我在我的 Class 中使用类型 class Doctrine\DBAL\Connection,这意味着我想要注入默认连接(@doctrine.dbal.default_connection),因为我只有一个连接。
namespace AppBundle\Classes;
use Doctrine\DBAL\Connection;
class SaveEvent
{
/** @var Connection */
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
// …
}
回答
// 已编辑
SimPod,你的问题的答案是 WORK FOR MANY DBAL CONNECTIONS USING PROXY 或 INJECT CONNECTIONS FOR EACH SERVICE 如上所述。
我知道你已经解决了这个问题,但我的回答可以帮助其他人。
您可以为学说连接指定包装器 class,不需要代理 class:
#config.yml
doctrine:
dbal:
connections:
default:
wrapper_class: AppBundle\Connections\ConnectionDefault
...
second:
wrapper_class: AppBundle\Connections\ConnectionSecond
...
连接应扩展 Doctrine\DBAL\Connection
:
<?php
namespace AppBundle\Connection;
use Doctrine\DBAL\Connection;
class ConnectionDefault extends Connection
{
}
class ConnectionSecond extends Connection
{
}
并创建服务别名:
#services.yml
services:
...
AppBundle\Connections\ConnectionDefault: '@doctrine.dbal.default_connection'
AppBundle\Connections\ConnectionSecond: '@doctrine.dbal.second_connection'
然后您可以通过键入提示将所需的连接简单地注入到服务中:
class MyService {
public function __construct(ConnectionDefault $connection) {...}
}
class MyOtherService {
public function __construct(ConnectionSecond $connection) {...}
}
3.4 版中有一项新功能,使该过程更加容易。
参见:Symfony 3.3 - Entity Manager injection into services with multiple database?
一个更简单的解决方案可以是:
#services.yml
services:
_defaults:
bind:
$dbSecond: '@doctrine.dbal.second_connection'
在控制器或服务中使用:
public function my(Request $request, Connection $dbSecond)
我正在使用 Doctrine 2,其中我有多个 DBAL 连接。我在 ORM 中也有多个 EntityManagers。
我需要能够以某种方式将特定的 DBAL 连接自动连接到其他 Symfony 3 服务中。
我可以使用 EntityManagerDecorator 自动装配任何 EntitiyManager,但不知道如何对连接做同样的事情。我能够从 EntityManager 获得连接,但我不认为这是可行的方法。
每个 DBAL 连接始终可以在具有以下标识符的服务容器中访问:
doctrine.dbal.[name]_connection
其中 [name]
是连接名称
我遇到了同样的问题并更准确地测试了它有效的方法和原因。
使用代理进行许多 DBAL 连接
编辑: 我做了一些代理摘要class。现在我的每个连接 class 都继承自该代理。它工作正常:)
<?php
#src/AppBundle/Connections/ConnectionProxy.php
namespace AppBundle\Connections;
use Doctrine\DBAL\Connection;
abstract class ConnectionProxy
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
public function __call($method, $arguments)
{
if (is_callable(array($this->connection, $method))) {
return call_user_func_array(array($this->connection, $method), $arguments);
} else {
return new \Exception("Call to undefined method '{$method}'");
}
}
}
我的连接默认值class:
<?php
#src/AppBundle/Connections/ConnectionDefault.php
namespace AppBundle\Connections;
class ConnectionDefault extends ConnectionProxy
{
}
第二个连接:
<?php
namespace AppBundle\Connections;
class ConnectionSecond extends ConnectionProxy
{
}
然后我为所有连接(2 个连接)手动添加到我的服务文件中:
AppBundle\Connections\ConnectionDefault:
public: true
class: AppBundle\Connections\ConnectionDefault
arguments: ['@doctrine.dbal.default_connection']
AppBundle\Connections\ConnectionSecond:
public: true
class: AppBundle\Connections\ConnectionSecond
arguments: ['@doctrine.dbal.second_connection']
然后当我使用它们的类型时我的连接会自动自动装配
class SaveEvent
{
/** @var Connection */
private $connection;
public function __construct(ConnectionDefault $connection)
{
$this->connection = $connection;
}
.....
为每个服务注入连接
最简单的选项 - 但需要单独创建每个服务并注入连接名称 - 这意味着在您的服务文件中手动连接参数**(app/config/services.yml)例如
AppBundle\Classes\SaveEvent:
public: true
arguments:
- '@doctrine.dbal.[connection_name]_connection'
其中 connection_name 是您的连接名称。 在下面的示例中,我们在 config.yml 中有两个连接,此值可以是“default”或“database2”:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_sqlite
charset: UTF8
path: '%database_path%'
database2:
driver: pdo_sqlite
charset: UTF8
path: '%database_path%'
仅适用于一个 DBAL 连接
当我们只有一个连接时,DBAL 连接的自动装配工作正常。如果我只保留默认连接(从 config.yml 中删除连接数据库 2)并在 app/config/services.yml:
中添加一些要自动连接的路径AppBundle\Classes\:
resource: '../../src/AppBundle/Classes'
public: true
如果我在我的 Class 中使用类型 class Doctrine\DBAL\Connection,这意味着我想要注入默认连接(@doctrine.dbal.default_connection),因为我只有一个连接。
namespace AppBundle\Classes;
use Doctrine\DBAL\Connection;
class SaveEvent
{
/** @var Connection */
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
// …
}
回答
// 已编辑 SimPod,你的问题的答案是 WORK FOR MANY DBAL CONNECTIONS USING PROXY 或 INJECT CONNECTIONS FOR EACH SERVICE 如上所述。
我知道你已经解决了这个问题,但我的回答可以帮助其他人。
您可以为学说连接指定包装器 class,不需要代理 class:
#config.yml
doctrine:
dbal:
connections:
default:
wrapper_class: AppBundle\Connections\ConnectionDefault
...
second:
wrapper_class: AppBundle\Connections\ConnectionSecond
...
连接应扩展 Doctrine\DBAL\Connection
:
<?php
namespace AppBundle\Connection;
use Doctrine\DBAL\Connection;
class ConnectionDefault extends Connection
{
}
class ConnectionSecond extends Connection
{
}
并创建服务别名:
#services.yml
services:
...
AppBundle\Connections\ConnectionDefault: '@doctrine.dbal.default_connection'
AppBundle\Connections\ConnectionSecond: '@doctrine.dbal.second_connection'
然后您可以通过键入提示将所需的连接简单地注入到服务中:
class MyService {
public function __construct(ConnectionDefault $connection) {...}
}
class MyOtherService {
public function __construct(ConnectionSecond $connection) {...}
}
3.4 版中有一项新功能,使该过程更加容易。 参见:Symfony 3.3 - Entity Manager injection into services with multiple database?
一个更简单的解决方案可以是:
#services.yml
services:
_defaults:
bind:
$dbSecond: '@doctrine.dbal.second_connection'
在控制器或服务中使用:
public function my(Request $request, Connection $dbSecond)