dom
dom

Reputation: 1

Symfony inject service container into doctrine connection wrapper

I try to inject the symfony service container into a dcotrine dynamic connection wrapper_class

use Doctrine\DBAL\Connection;    
class DynamicConnection extends Connection
{
    public $container;

    /**
     * @required
     * @param $container
     */
    public function setContainer(ContainerInterface $container)
    {
        $this->container = $container;
    }
}

I also tried to inject it with the service.yaml

    App\Service\Database\DynamicConnection:
    calls:
        - [setContainer, ['@service_container']]

But this is also not working. How can i inject the service container here? My goal here is to get a variable of the service container:

$this->container->get('my.string.variable')

Upvotes: 0

Views: 2114

Answers (2)

fabpico
fabpico

Reputation: 2917

Not exactly injecting the Container (bad practice), but supposing we want to do inject any service.

Constructor injection was not right for me, it needed plenty of other parameters, which should be coming from configurations:

 public function __construct(
        #[SensitiveParameter]
        array $params,
        protected Driver $driver,
        ?Configuration $config = null,
    )

Setter injection did not work for me (I assume the wrapper class is not going through the dependency injection process, just the class is being passed to the Connection initialization?).

I did not want to build an extra compiler pass for that.

Since neither constructor injection, nor setter injection, nor compiler pass were fit for me, I just used Adapter pattern. I created a new service that was easilly constructor-injectable, which calls DBAL Connection methods.

<?php declare(strict_types=1);

namespace App\Infrastructure\Database;

use App\Business\Security\Authenticator;
use Doctrine\DBAL\Connection as DoctrineDBALConnection;
use Doctrine\DBAL\Query\QueryBuilder;

final class Connection
{
    private DoctrineDBALConnection $connection;
    private Authenticator $authenticator;

    public function __construct(DoctrineDBALConnection $connection, Authenticator $authenticator)
    {
        $this->connection = $connection;
        $this->authenticator = $authenticator;
    }

    public function createQueryBuilder(): QueryBuilder
    {
        // to your extra stuff here
        return $this->connection->createQueryBuilder();
    }
}

Upvotes: 0

sunix
sunix

Reputation: 146

You can do this by adding a CompilerPass. For simple CompilerPass, you can add it directly in your application Kernel class by implementing CompilerPassInterface:

class Kernel extends BaseKernel implements CompilerPassInterface
{
    use MicroKernelTrait;

    ...


    public function process(ContainerBuilder $container)
    {

       $container
          ->getDefinition('doctrine.dbal.default_connection')
          ->addMethodCall('setContainer', [
             new Reference('service_container')
           ]);
    }

}

Note however that as mentioned by other users, this is not a very good practice. You should inject what you need precisely instead of Container service.

Upvotes: 3

Related Questions