简体   繁体   中英

Symfony 2.1 - Custom Json Annotation Listener

For a Symfony 2.1 project, I'm trying to create a new annotation @Json() that will register a listener that will create the JsonResponse object automatically when I return an array. I've got it working, but for some reason the listener is always called, even on methods that don't have the @Json annotation. I'm assuming my approach works, since the Sensio extra bundle does this with the @Template annotation.

Here is my annotation code.

<?php

namespace Company\Bundle\Annotations;

/**
 * @Annotation
 */
class Json extends \Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationAnnotation
{
    public function getAliasName()
    {
        return 'json';
    }
}

Here is my listener code.

<?php

namespace Company\Bundle\Listener\Response\Json;

class JsonListener
{
    //..

    public function onKernelView(GetResponseForControllerResultEvent $event)
    {
        $request = $event->getRequest();
        $data = $event->getControllerResult();

        if(is_array($data) || is_object($data)) {
            if ($request->attributes->get('_json')) {
                $event->setResponse(new JsonResponse($data));
            }
        }
    }
}

This is my yaml definition for the listener.

json.listener:
            class:      Company\Bundle\Listener\Response\Json
            arguments:  [@service_container]
            tags:
                - { name: kernel.event_listener, event: kernel.view, method: onKernelView }

I'm obviously missing something here because its being registered as a kernel.view listener. How do I change this so that it is only called when a @Json() annotation is present on the controller action?

Not pretend to be the definitive answer.

I'm not sure why your are extending ConfigurationAnnotation : its constructor accepts an array , but you don't need any configuration for your annotation. Instead, implement ConfigurationInterface :

namespace Company\Bundle\Annotations;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;

/**
 * @Annotation
 */
class Json implements ConfigurationInterface
{
    public function getAliasName()
    {
        return 'json';
    }

    public function allowArray()
    {
        return false;
    }
}

Sensio ControllerListener from SensionFrameworkExtraBundle will read your annotation (merging class with methods annotations) and perform this check:

if ($configuration instanceof ConfigurationInterface) {
    if ($configuration->allowArray()) {
        $configurations['_'.$configuration->getAliasName()][] = $configuration;
    } else {
        $configurations['_'.$configuration->getAliasName()] = $configuration;
    }
}

Setting a request attribute prefixed with _ . You are correctly checking for _json , so it should work. Try dumping $request->attributes in your view event listener. Be sure that your json.listener service is correctly loaded too (dump them with php app/console container:debug >> container.txt ).

If it doesn't work, try adding some debug and print statements here (find ControllerListener.php in your vendor folder):

var_dump(array_keys($configurations)); // Should contain _json

Remember to make a copy of it before edits, otherwise Composer will throw and error when updating dependencies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM