So, here is a controller I've 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 to make this controller 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:
Catchable Fatal Error: Argument 1 passed to MDP\API\ImageBundle\Controller\RetrieverController::__construct() must be an instance of Symfony\Component\HttpFoundation\JsonResponse, none given, 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 am in dev mode, I see that Symfony generate this file in the cached files...
class RetrieverController__JMSInjector
{
public static function inject($container) {
$instance = new \MDP\API\ImageBundle\Controller\RetrieverController();
return $instance;
}
}
How can I make it so that the arguments are added correctly to the controller, like specified in my services.xml
file?
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
So, I fixed my problem. I had to stop using Annotations in my controller and changed my routing.yml so write the routes directly.
image_retrieve:
pattern: /image/{amount}
defaults: { _controller: mdp_api_image_retriever_retrieve:retrieve }
requirements:
_method: GET
That fixed the whole problem. The problem with annotations is that on 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, it tries to call the method call_user_func from the returned data, which was null.
In other words, using Annotation and creating your Controllers as Service does NOT work together. I lost 4 hours debugging this issue, so I hope this might help someone in the future :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With