Skip to content

Commit

Permalink
Merge pull request #1296 from HypeMC/autowire-connection-by-argument-…
Browse files Browse the repository at this point in the history
…type-and-name

Autowire connections by argument type and name
  • Loading branch information
ostrolucky committed Mar 8, 2021
2 parents e45b71c + 6331923 commit a8020a0
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 2 deletions.
11 changes: 9 additions & 2 deletions DependencyInjection/DoctrineExtension.php
Expand Up @@ -9,6 +9,7 @@
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Connections\MasterSlaveConnection;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Logging\LoggerChain;
Expand Down Expand Up @@ -214,8 +215,10 @@ protected function loadDbalConnection($name, array $connection, ContainerBuilder
// connection
$options = $this->getConnectionOptions($connection);

$connectionId = sprintf('doctrine.dbal.%s_connection', $name);

$def = $container
->setDefinition(sprintf('doctrine.dbal.%s_connection', $name), new ChildDefinition('doctrine.dbal.connection'))
->setDefinition($connectionId, new ChildDefinition('doctrine.dbal.connection'))
->setPublic(true)
->setArguments([
$options,
Expand All @@ -224,6 +227,10 @@ protected function loadDbalConnection($name, array $connection, ContainerBuilder
$connection['mapping_types'],
]);

$container
->registerAliasForArgument($connectionId, Connection::class, sprintf('%sConnection', $name))
->setPublic(false);

// Set class in case "wrapper_class" option was used to assist IDEs
if (isset($options['wrapperClass'])) {
$def->setClass($options['wrapperClass']);
Expand All @@ -235,7 +242,7 @@ protected function loadDbalConnection($name, array $connection, ContainerBuilder

// Create a shard_manager for this connection
if (isset($options['shards'])) {
$shardManagerDefinition = new Definition($options['shardManagerClass'], [new Reference(sprintf('doctrine.dbal.%s_connection', $name))]);
$shardManagerDefinition = new Definition($options['shardManagerClass'], [new Reference($connectionId)]);
$container->setDefinition(sprintf('doctrine.dbal.%s_shard_manager', $name), $shardManagerDefinition);
}

Expand Down
15 changes: 15 additions & 0 deletions Resources/doc/configuration.rst
Expand Up @@ -1088,4 +1088,19 @@ which is the first one defined or the one configured via the
Each connection is also accessible via the ``doctrine.dbal.[name]_connection``
service where ``[name]`` is the name of the connection.

Autowiring multiple Connections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can autowire different connections by type-hinting your service arguments with
the following syntax: ``Doctrine\DBAL\Connection $<connection name>Connection``.
For example, to inject a connection with the name ``purchase_logs`` use this:

.. code-block:: diff
- public function __construct(Connection $connection)
+ public function __construct(Connection $purchaseLogsConnection)
{
$this->connection = $purchaseLogsConnection;
}
.. _DBAL documentation: https://www.doctrine-project.org/projects/doctrine-dbal/en/2.10/index.html
30 changes: 30 additions & 0 deletions Tests/DependencyInjection/DoctrineExtensionTest.php
Expand Up @@ -54,6 +54,36 @@ public function testAutowiringAlias(): void
}
}

public function testConnectionAutowiringAlias()
{
$container = $this->getContainer();
$extension = new DoctrineExtension();

$config = BundleConfigurationBuilder::createBuilder()
->addConnection([
'connections' => [
'default' => ['password' => 'foo'],
'purchase_logs' => ['password' => 'foo'],
],
])
->build();

$extension->load([$config], $container);

$expectedAliases = [
Connection::class . ' $defaultConnection' => 'doctrine.dbal.default_connection',
Connection::class . ' $purchaseLogsConnection' => 'doctrine.dbal.purchase_logs_connection',
];

foreach ($expectedAliases as $id => $target) {
$this->assertTrue($container->hasAlias($id), sprintf('The container should have a `%s` alias for autowiring support.', $id));

$alias = $container->getAlias($id);
$this->assertEquals($target, (string) $alias, sprintf('The autowiring for `%s` should use `%s`.', $id, $target));
$this->assertFalse($alias->isPublic(), sprintf('The autowiring alias for `%s` should be private.', $id));
}
}

public function testEntityManagerAutowiringAlias()
{
if (! interface_exists(EntityManagerInterface::class)) {
Expand Down

0 comments on commit a8020a0

Please sign in to comment.