1

I'm having trouble achieving something that should be simple using FOSRestBundle.

If I return an object, it works as intended. The JSON response will look something like

{ 
  id: ..., 
  property: ... 
}

What I'd like to do is return, on all requests and status codes, a envelope for the response, something like

{
  meta: {
    code: 200,
    message: 'OK',
  }
  data: {
    id: ...,
    property: ...
  }
}

This way, clients can write simple code to detect errors, where responses would look something like:

{
  meta: {
    code: 400,
    message: 'Your request failed because...',
  }
  data: {}
}

I want to return this from multiple controllers, and return it only on JSON or XML requests. My first thought was to use a ResponseListener, check the format of the request, and modify the response if need be. Or, maybe, just set up a class something like \Model\APIRequestFormatter, and from my controller, instead of doing a return $entity; do return APIRequestFormatter->Format($entity);

Both of these approaches seem flawed to me, does anyone have any tips?

Pez
  • 1,251
  • 16
  • 32

1 Answers1

4

You should have a look at this really complete blog post : http://williamdurand.fr/2012/08/02/rest-apis-with-symfony2-the-right-way/

William Durand talks about how to create a good REST Api and about JSON response with the correct status code.

If you are following what William wrote in his article, you will have a JSON response based on this format :

{
    code: 400,
    message: "Your message",
    first_data: "...",
    second_data: "...",
    ...
}

Which is not exactly what you are looking for. But I think the code your clients will have to write will be as simple as what you want with the format you proposed :

{
  meta: {
    code: 400,
    message: 'Your request failed because...',
  }
  data: {}
}

Maybe you can show what you did in your controller so my answer could be more precise.


Update:

With the following controller, you should be able to return the JSON Response you want :

use Symfony\Component\HttpFoundation\JsonResponse;

class MyController{
    //...
    public function myAction(){
        $myStatusCode = 400;

        return new JSonResponse(
            array('meta' => array('code' => $myStatusCode,
                                  'message' => 'Your request failed because...'),
                  'data' => array('your datas')
            ),
            $myStatusCode
        );
    }
    //...
}

This will create a response with the correct status code in the header and it allows you to add the message and status code you want in your JSon response.

Ian Letourneau
  • 415
  • 5
  • 17
  • Thank you very much for the response. I did follow that tutorial fairly closely. The issue is that the responses you've shown here are indeed what error responses look like, but not what successful entity responses look like. I was hoping to be able to add a consistent envelope to all responses, error and success alike, but it doesn't appear to me that there's a good way to do this. – Pez Mar 20 '14 at 23:21
  • @Pez Have you tried to use curl to send a request to your controller? When you send a request, you receive a status code in the response's header. For instance, I am sending this simple request `curl -v -H "Accept: application/json" -H "Content-type: application/json" localhost/my_api.json `. If it's successful, the header of the response I will receive will be : `HTTP/1.1 200 OK`. So, based on this data, I will be able to know if it was successful or not. I know it's not exactly what you are trying to acheive so if it isn't good for you let me know. I will be happy to look for other solutions – Ian Letourneau Mar 21 '14 at 05:39
  • I think I found another question that could help you : http://stackoverflow.com/questions/12385923/handle-errors-in-ajax-within-symfony2-controller I know it's about errors message but the answer provided by Florian Eckerstorfer allow you to add anything you want. I updated my answer. – Ian Letourneau Mar 21 '14 at 05:51