eddy147
eddy147

Reputation: 4993

Symfony3, DI, Error when injecting a custom repository in controller

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 :)

Upvotes: 1

Views: 541

Answers (1)

Tobias Xy
Tobias Xy

Reputation: 2069

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.

Upvotes: 2

Related Questions