3
votes

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
If I had to guess then I suspect your InvoiceGenerator is somehow dependent on HttpException. Or perhaps whatever you are injecting MyClass into. - Cerad
Exception should not be a services. See "exclude" in docs. Here is config example with "exclude" - Tomas Votruba

1 Answers

1
votes

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.