1

getting the following exception:

Catchable Fatal Error: Argument 1 passed to AppBundle\Controller\AudienceController::__construct() must be an instance of AppBundle\Repository\AudienceRepository, none given, called in /home/eddy/Projects/tm/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php on line 162 and defined

Meaning, I defined my controller with a custom repository as a constructor argument, but or the repository is never passed or not created. I tried debugging into ControllerResolver but to no avail.

[services.yml]
services:
    app.audience_repository:
        class: Doctrine\ORM\EntityRepository
        factory: ["@doctrine.orm.entity_manager", getRepository]
        arguments:
            - AppBundle\Entity\Audience
    app.audience_controller:
        class: AppBundle\Controller\AudienceController
        arguments:
            - "@app.audience_repository"


[AppBundle\Controller\AudienceController.php]
    class AudienceController extends Controller
    {
        /**
         * @var AudienceRepository
         */
        private $repository;

        /**
         * @param AudienceRepository $repository
         */
        public function __construct(AudienceRepository $repository)
        {
            $this->repository = $repository;
        }

[AppBundle\Repository\AudienceRepository]
class AudienceRepository extends EntityRepository
{
    public function save(Audience $audience)
    {
        $this->getEntityManager()->persist($audience);
        $this->getEntityManager()->flush();
    }
}

[AppBundle\Entity\Audience.php]
/**
 * Audience
 *
 * @ORM\Table(name="audience")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\AudienceRepository")
 */
class Audience

I think this is according to http://php-and-symfony.matthiasnoback.nl/2014/05/inject-a-repository-instead-of-an-entity-manager/ with a modification for symfony3 (see https://stackoverflow.com/a/20348821/30759) and should work, but I keep getting this error.

Stacktrace:
at ErrorHandler ->handleError ('4096', 'Argument 1 passed to AppBundle\Controller\AudienceController::__construct() must be an instance of AppBundle\Repository\AudienceRepository, none given, called in /home/eddy/Projects/tm/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php on line 162 and defined', '/home/eddy/Projects/tm/src/AppBundle/Controller/AudienceController.php', '23', array()) 
in src/AppBundle/Controller/AudienceController.php at line 23   + 
at AudienceController ->__construct () 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php at line 162   + 
at ControllerResolver ->instantiateController ('AppBundle\Controller\AudienceController') 
in vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php at line 81   + 
at ControllerResolver ->instantiateController ('AppBundle\Controller\AudienceController') 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php at line 150   + 
at ControllerResolver ->createController ('AppBundle\Controller\AudienceController::newAction') 
in vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php at line 73   + 
at ControllerResolver ->createController ('AppBundle\Controller\AudienceController::newAction') 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php at line 76   + 
at ControllerResolver ->getController (object(Request)) 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php at line 46   + 
at TraceableControllerResolver ->getController (object(Request)) 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php at line 127   + 
at HttpKernel ->handleRaw (object(Request), '1') 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php at line 62   + 
at HttpKernel ->handle (object(Request), '1', true) 
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php at line 169   + 
at Kernel ->handle (object(Request)) 
in web/app_dev.php at line 30   + 
at require ('/home/eddy/Projects/tm/web/app_dev.php') 
in vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_dev.php at line 40   + 

Any help is greatly appreciated :)

1
  • You need to tell your route that the controller is defined as a service: symfony.com/doc/current/cookbook/controller/service.html. By the way, you won't be able to use any of the helper methods (like render) from the base controller class unless you add setContainer to your controller service definition. Commented Mar 21, 2016 at 12:10

1 Answer 1

2

In the article you linked to ("Inject a repository instead of an entity manager") he writes about "normal" services and I also think you should inject repositories instead of the entity manager if applicable. But: In symfony a controller is not a service by default.

There are basically two options:

Option 1: Tell Symfony that your Controller is a service

As this is a bit more complex, I just leave you this link here: How to Define Controllers as Services

In that case you should not extend the Controller base class, which in turn means you can't use the methods provided by it. If you don't use them anyway, this is okay and you can go for it.

If not (for example you want to use the "render" method), you also have to inject the service container into your controller using the setContainer method and you did a lot of work to just use the base controller again. That's why I would recommend using Option 2.

Option 2: Use the helper methods from the Controller class (I prefer this one)

$audienceRepo = $this->getDoctrine()->getRepository(Audience::class);

In that case you don't have to define the controller as service and you can just use it as before.

Sign up to request clarification or add additional context in comments.

5 Comments

Option 3: Extend your controller from the base controller and call setContainer from your service definition. Inject the repository as well as other controller specific services into the constructor. Best of both worlds.
That is what I (tried to) describe in option 1, but in my opinion it is too much effort to just avoid using the "get" method of the base controller. But of course it is possible, if you want to do it.
Adding one line to a dervice definition in exchange for getting all the standard controller helper functions seems reasonable to me but too each their own.
Let me see if I understand option #2: so the repository is then not injected as a dependency in the constructor?
Exactly. Basically this is a violation of DI principles, because you request the service from inside the controller, but it is easier to use. You should also read this article, to get more information why to do it (or why not): knpuniversity.com/screencast/question-answer-day/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.