ovesco
ovesco

Reputation: 633

symfony2 get paramConverter value in custom annotation

I'm trying to create my own symfony2 annotations. What I'm trying to achieve is get the paramConverter object in my annotation (in my controller), like

/**
 * @ParamConverter("member", class="AppBundle:Member")
 * @Route("my/route/{member}", name="my_route")
 * @MyCustomAnnotation("member", some_other_stuff="...")
 */
public function myAction(Member $member) {...}

The purpose here is to get the "member" in my annotation, so I can work on it before it is passed to the controller action

Currently, my annotation "reader" is working as a service

MyCustomAnnotationDriver:
            class: Vendor\Bundle\Driver\CustomAnnotationDriver
            tags: [{name: kernel.event_listener, event: kernel.controller, method: onKernelController}]
            arguments: [@annotation_reader]

How can I achieve this ?

Upvotes: 2

Views: 1262

Answers (2)

ovesco
ovesco

Reputation: 633

So I found a solution lurking in the doc. In fact, the event is working with the Request, so for every params in my route, I check the corresponding ParamConverter, and get the entity.

Here is what I get :

public function onKernelController(FilterControllerEvent $event)
{
        if (!is_array($controller = $event->getController()))
            return; //Annotation only available in controllers

        $object      = new \ReflectionObject($controller[0]);
        $method      = $object->getMethod($controller[1]);
        $annotations = new ArrayCollection();
        $params      = new ArrayCollection();

        foreach ($this->reader->getMethodAnnotations($method) as $configuration) {

            if($configuration instanceof SecureResource) //SecureResource is my annotation
                $annotations->add($configuration);
            else if($configuration instanceof \Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter)
                $params->add($configuration);
        }

        foreach($annotations as $ann) {

            $name = $ann->resource; // member in my case

            $param = $params->filter(

                function($entry) use ($name){
                    if($entry->getName() == $name) return $entry;
                } //Get the corresponding paramConverter to get the repo

            )[0];

            $entityId = $event->getRequest()->attributes->get('_route_params')[$name];
            $entity   = $this->em->getRepository($param->getClass())->find($entityId);

            //.. do stuff with your entity

        }
        // ...
}

Upvotes: 0

Jovan Perovic
Jovan Perovic

Reputation: 20201

I have done it few months ago but I choose much simpler approach. My use-case was to inject object based on currently logged user (either Profile or Teacher).

Check this GIST out:

GIST: https://gist.github.com/24d3b1778bc86429c7b3.git

PASTEBIN (gist currently doesn't work): http://pastebin.com/CBjrHvbM

Then, register the converter as:

<service id="my_param_converter" class="AcmeBundle\Services\RoleParamConverter">
    <argument type="service" id="security.context"/>
    <argument type="service" id="doctrine.orm.entity_manager"/>
    <tag name="request.param_converter" converter="role_converter"/>
</service>

Finally, use it:

/**
 * @Route("/news")
 * @ParamConverter("profile", class="AcmeBundle:Profile", converter="role_converter")
 */
public function indexAction(Profile $profile){
    // action's body
}

You can also, apply this custom ParamConverter to controller's class.

Upvotes: 2

Related Questions