JMSDiExtraBundle icon indicating copy to clipboard operation
JMSDiExtraBundle copied to clipboard

Error when using @Service on a controller class

Open jeremymarc opened this issue 12 years ago • 6 comments

[2013-02-13 06:44:28] request.CRITICAL: ErrorException: Warning: call_user_func() expects parameter 1 to be a valid callback, no array or string given in app/cache/dev/classes.php line 244 (uncaught exception) at app/cache/dev/classes.php line 244

When commenting this code it's working. if (null !== $metadata->getOutsideClassMetadata()->id && 0 !== strpos($metadata->getOutsideClassMetadata()->id, '_jms_di_extra.unnamed.service')) { return; }

strpos($metadata->getOutsideClassMetadata()->id, '_jms_di_extra.unnamed.service') is returning false.

jeremymarc avatar Feb 13 '13 05:02 jeremymarc

Do you use the controller as a non-service controller? Is the controller class inheriting from another class?

schmittjoh avatar Feb 13 '13 08:02 schmittjoh

/** @Service("controller.catalog") **/ class CatalogController extends Controller { ... }

Im trying to call a method of the controller, doing : $container->get('controller.catalog')->indexAction();

jeremymarc avatar Feb 13 '13 16:02 jeremymarc

I also had the same issue with my controllers. Did you find a way to prevent this for good ? Note when removing the @Service annotation from my controller I get a exception saying that the service I'm trying to call from the controller (user defined service via @Service annotation) does not exist.

EDIT : Found how to solve this : The @Route annotation now has a service attribute in wich one needs to had the service id.

I.e : /**

  • @Service("test")
  • @Route ("/test", service="test") **/

rrajkomar avatar Mar 11 '13 14:03 rrajkomar

ControllerResolver#createInjector can return null, but ControllerResolver#instantiateController(the caller) does not handle the case when null is returned.

ianfp avatar Jan 05 '17 19:01 ianfp

I just stumbled upon this issue again:

My SecurityController is a service

/**
 * @DI\Service("app.controller.security")
 * @Route(service="app.controller.security")
 */
class SecurityController
{
    /** ...stuff... */
    /**
     * @Route("/login", name="login")
     * @Template("security/login.html.twig")
     */
    public function loginAction(): array { ... }
}

And in my template I have

{% if not is_granted('IS_AUTHENTICATED_FULLY') %}
  {{ render(controller('AppBundle:Security:loginAction')) }}
{% endif %}

Which results in the following szenario (see comments):

# JMS\DiExtraBundle\HttpKernel\ControllerResolver

protected function instantiateController($class)
    {
        if ($this->container->has($class)) { // nope!
            return $this->container->get($class);
        }

        // $class = 'AppBundle\Controller\SecurityController'
        $injector = $this->createInjector($class);
       // $injector = null, because the class is not listed in cache/dev/jsm_diextra/controller_injectors
        $controller = call_user_func($injector, $this->container); // -> An exception has been thrown during the rendering of a template ("Warning: call_user_func() expects parameter 1 to be a valid callback, no array or string given").

        if ($controller instanceof ContainerAwareInterface) {
            $controller->setContainer($this->container);
        }

        return $controller;
    }

Basster avatar Mar 14 '17 21:03 Basster

Github was my rubberduck :duck: :smirk:

After writing this down, I figured it out by myself. For anyone with the same issue, here's the solution:

{% if not is_granted('IS_AUTHENTICATED_FULLY') %}
  {{ render(controller('app.controller.security:loginAction')) }}
{% endif %}

Where would be a nice place to document that?

Edit: Makes perfect sense now... http://symfony.com/doc/current/controller/service.html#referring-to-the-service

Basster avatar Mar 14 '17 21:03 Basster