Reputation: 633
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
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
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