Trying to define my controllers as a service in Symfony2 - arguments are never passed to the constructor

So, here is the controller I just built:

namespace MDP\API\ImageBundle\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class RetrieverController { private $jsonResponse; private $request; public function __construct(JsonResponse $jsonResponse, Request $request) { $this->jsonResponse = $jsonResponse; $this->request = $request; } /** * @Route("/image/{amount}") * @Template("MDPAPIImageBundle:Retriever:index.json.twig") */ public function retrieve($amount) { } } 

I want this controller to work as a service to use DependencyInjection. So here is my services.xml file:

 <?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="mdpapi_image.json_response" class="Symfony\Component\HttpFoundation\JsonResponse" /> <service id="mdpapi_image.request" class="Symfony\Component\HttpFoundation\Request" /> <service id="mdpapi_image.controller.retriever" class="MDP\API\ImageBundle\Controller\RetrieverController"> <argument type="service" id="mdpapi_image.json_response" /> <argument type="service" id="mdpapi_image.request" /> </service> </services> </container> 

However, when I try to execute my controller, I always get this exception:

Workaround fatal error: argument 1 passed to MDP \ API \ ImageBundle \ Controller \ RetrieverController :: __ construct () must be an instance of Symfony \ Component \ HttpFoundation \ JsonResponse not specified, called in / home / steve / projects / APIs / app / cache / dev / jms _diextra / controller_injectors / MDPAPIImageBundleControllerRetrieverController.php on line 13 and defined in /home/steve/projects/ImageAPI/ImageBundle/Controller/RetrieverController.php line 13

When I'm in dev mode, I see that Symfony generates this file in cached files ...

 class RetrieverController__JMSInjector { public static function inject($container) { $instance = new \MDP\API\ImageBundle\Controller\RetrieverController(); return $instance; } } 

How can I make sure that the arguments are correctly added to the controller, as indicated in my services.xml ?

+6
source share
3 answers

Just found the answer to your question, hope this helps you (or others who find this question)

 <?php namespace MDP\API\ImageBundle\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; /** * @Route("/image", service="mdpapi_image.controller.retriever") */ class RetrieverController { private $jsonResponse; private $request; public function __construct(JsonResponse $jsonResponse, Request $request) { $this->jsonResponse = $jsonResponse; $this->request = $request; } /** * @Route("/{amount}") * @Template("MDPAPIImageBundle:Retriever:index.json.twig") */ public function retrieve($amount) { } } 

Sources:

http://richardmiller.co.uk/2011/10/25/symfony2-routing-to-controller-as-service-with-annotations/

http://symfony.com/doc/current/cookbook/controller/service.html

+3
source

So, I fixed my problem. I had to stop using annotations in my controller and change my routing.yml, so write routes directly.

 image_retrieve: pattern: /image/{amount} defaults: { _controller: mdp_api_image_retriever_retrieve:retrieve } requirements: _method: GET 

This fixed the whole problem. The problem with annotations is that in this class (JMS \ DiExtraBundle \ HttpKernel \ ControllerResolver) on line 90 in the Symfony core, you see this core:

 // If the cache warmer tries to warm up a service controller that uses // annotations, we need to bail out as this is handled by the service // container directly. if (null !== $metadata->getOutsideClassMetadata()->id && 0 !== strpos($metadata->getOutsideClassMetadata()->id, '_jms_di_extra.unnamed.service')) { return; } 

Then, on line 69, he tries to call the call_user_func method from the returned data, which was null.

In other words, using Annotation and building your controllers as services does NOT work together. I lost 4 hours debugging this problem, so hope this can help someone in the future :)

+1
source

It looks like you forgot to write an extension class that loads your services.xml file:

 namespace MDP\API\ImageBundle\DependencyInjection; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\Config\FileLocator; class ImageExtension extends Extension { /** * @param array $configs * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container */ public function load(array $configs, ContainerBuilder $container) { $loader = new XmlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') ); $loader->load('services.xml'); } } 
0
source

Source: https://habr.com/ru/post/926246/


All Articles