Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 + FOSRestBundle: Enable/disable REST functionality per controller/action?

A part of my application will be available as an API, so some of my pages needs to be available in JSON or XML (based on the Accept header 'Content Type').

I've used the FOSRestBundle and it works very well, but now ALL my pages are available in XML (or JSON) when sending Accept header 'Content Type: application/xml'.

So, I would like to enable/disable this functionality for some of my controllers/actions. I would be ideal to do this using annotations.

Is that possible?

My config.yml:

fos_rest:
    view:
        formats:
            rss: false
            xml: true 
            json: true
        templating_formats:
            html: true
        force_redirects:
            html: false
        failed_validation: HTTP_BAD_REQUEST
        default_engine: twig
        view_response_listener: force
    body_listener:
        decoders:
            json: acme.decoder.json
            xml: fos_rest.decoder.xml
    format_listener:
        default_priorities: ['html', 'xml', 'json', '*/*']
        fallback_format: html
        prefer_extension: false    
like image 636
Jeff Maes Avatar asked Aug 09 '12 13:08

Jeff Maes


2 Answers

According to the RestBundle's documentation, you won't get an XML output if you don't use a View in your controller. So, if you don't use the @View annotation, or a View::create() in your action, and you return a classic response, you will get a HTML output.

If you want to force the format for some reasons, you can turn the prefer_extension to true and adjust the routing definition:

my_route:
    pattern:  /my-route
    defaults: { _controller: AcmeDemoBundle:action, _format: <format> }

Where <format> is the format you want to force.

like image 71
William Durand Avatar answered Oct 11 '22 12:10

William Durand


You can set view_response_listener to false (default is force). And then add @View annotation to each of your controller classes, where you want to use REST.

Example will make it clearer.

A controler without REST:

/**
 * @Route("/comments")
 */
class CommentsControler extends Controller
{
    /**
     * @Route("/")
     * @Method({"POST"})
     */
    public function newAction() { ... }

    /**
     * @Route("/{id}")
     */
    public function detailAction($id) { ... }

    ...
}

And another controller with REST. Notice that only @View annotation for the class is required (unless you want to override response status code).

/**
 * @View
 * @Route("/api/comments")
 */
class RestfulCommentsControler extends Controller
{
    /**
     * @Route("/")
     * @Method({"POST"})
     */
    public function newAction() { ... }

    /**
     * @Route("/{id}")
     */
    public function detailAction($id) { ... }

    /**
     * @View(statusCode=204)
     * @Route("/{id}/delete")
     */
    public function deleteAction($id) { ... }

    ...
}
  • View is FOS\RestBundle\Controller\Annotations\View
  • Route is Symfony\Component\Routing\Annotation\Route
like image 32
Jan Včelák Avatar answered Oct 11 '22 11:10

Jan Včelák