1
votes

I'm trying to emulate the behavior of Route Symfony annotation(documentation), which extends Symfony\Component\Routing\Annotation\Route adding the service property:

class Route extends BaseRoute
{
    protected $service;

    public function setService($service)
    {
        $this->service = $service;
    }

    // ...
}

It adds the service property in order to set the _controller parameter to servicename:method when controller is actually a service. This is done in the AnnotatedRouteControllerLoader class:

protected function configureRoute(Route $route, \ReflectionClass $class, 
    \ReflectionMethod $method, $annot)
{
    // ...
    if ($classAnnot && $service = $classAnnot->getService()) {
        $route->setDefault('_controller', $service.':'.$method->getName());
    } else {
        // Not a service ...
    }

    // ...
}

My question is how/when the setService($service) is invoked?

I've tried to define my custom MyCustomRoute annotation (with the above service property), loop each container service and call setService($serviceId) to "notify" that the controller is actually a service:

foreach ($container->getServiceIds() as $serviceId) {
    if ($container->hasDefinition($serviceId)) {
        $definition = $container->getDefinition($serviceId);
        $reflector = new \ReflectionClass($definition->getClass());

        // If the service is a controller then flag it for the 
        // AnnotatedRouteControllerLoader
        if ($annot = $reader->getClassAnnotation($reflector, 
            'My\CustomAnnotations\MyCustomRoute')) {
            $annot->setServiceName($serviceId);
        }
    }
}

Here $container is Symfony service container, $reader is doctrine annotation reader.

This is not working because annotation is read again in AnnotatedRouteControllerLoader resulting in a different instance, loosing the service property.

I'm using the routing component alone (without the entire Symfony framework).

1

1 Answers

0
votes

The Route class is declared as a service, refering to the doc, you can inject dependencies by controller, but also with "setter injection". take a look here: http://symfony.com/doc/current/book/service_container.html#optional-dependencies-setter-injection

So you can declare your service as:

my_custom.router:
    class:     "Acme\MyBundle\MyServices\MyRouter"
    calls:
        - [setService, ["@service_key"]]