Symfony 3.3 Dependency Injection changes

Viewed 286

In Synfony 3.3, the new best practice for DI

is to use normal constructor dependency injection (or "action" injection in controllers) instead of fetching public services via $this->get() (though that does still work)

as seen in offical documentation

So no need to specify services as we can type hint them in class controllers :

class InvoiceMailer
{
    private $generator;

    public function __construct(InvoiceGenerator $generator)
    {
        $this->generator = $generator
    }

    // ...
}

This seems to work well, but what if I extends a class and add more parameters in my constructors ???

use Symfony\Component\HttpKernel\Exception\HttpException;

class MyClass extends HttpException
{
    private $generator;

    public function __construct(InvoiceGenerator $generator, \Exception $previous = null, array $headers = [], $code = 0)
    {
        $this->generator = $generator;
        $statusCode      = $generator->getStatusCode();
        $message         = $generator->getTitle();

        parent::__construct($statusCode, $message, $previous, $headers, $code);
    }

    // ...
}

Now I get a circular reference error :

[Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException] Circular reference detected for service "AppBundle\Service\MyClass", path: "AppBundle\Service\MyClass -> AppBundle\Service\MyClass".

So, what is the best practice in this case ??

Thanks.

1 Answers

For that case you might have to define the service explicitly as \Exception $previous argument in fact is parent class of MyClass (through HttpException) so the autowiring method try to inject/create an instance of MyClass again on this argument, result: "Circular Reference".

This is an abstraction of what happens to you:

namespace App\Foo;

class MyClass extends \Exception
{
    public function __construct(\Exception $previous = null)
    {
    }
}

Same error, so you can to solve it passing a null value to this argument:

# service.yml
services:
    # ...
    App\Foo\MyClass: 
        $previous: ~

or changing its definition manually in a compiler pass or DI extension.

Related