2

I have RESTful service that is available by endpoints.

For example, I request api/main and get JSON data from server.

For response I use:

return response()->json(["categories" => $categories]);

How to control format of response passing parameter in URL?

As sample I need this: api/main?format=json|html that it will work for each response in controllers.

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
Darama
  • 3,130
  • 7
  • 25
  • 34

3 Answers3

8

One option would be to use Middleware for this. The below example assumes that you'll always be returning view('...', [/* some data */]) i.e. a view with data.

When the "format" should be json, the below will return the data array passed to the view instead of the compiled view itself. You would then just apply this middleware to the routes that can have json and html returned.

public function handle($request, Closure $next)
{
    $response = $next($request);

    if ($request->input('format') === 'json') {
        $response->setContent(
            $response->getOriginalContent()->getData()
        );
    }

    return $response;
}
Rwd
  • 34,180
  • 6
  • 64
  • 78
5

You can use for this Response macros. For example in AppServiceProvider inside boot method you can add:

\Response::macro('custom', function($view, $data) {
    if (\Request::input('format') == 'json') {
            return response()->json($data);
    }
    return view($view, $data);
});

and in your controller you can use now:

$data = [
   'key' => 'value',
];

return response()->custom('your.view', $data);

If you run now for example GET /categories you will get normal HTML page, but if you run GET /categories?format=json you will get Json response. However depending on your needs you might need to customize it much more to handle for example also redirects.

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
0

With your format query parameter example the controller code would look something like this:

public function main(Request $request)
{
    $data = [
        'categories' => /* ... */
    ];

    if ($request->input('format') === 'json') {
        return response()->json(data);
    }

    return view('main', $data);
}

Alternatively you could simply check if the incoming request is an AJAX call via $request->input('format') === 'json' with $request->ajax()

nCrazed
  • 1,025
  • 6
  • 20
  • Problem is that I dont want to write this code in each controller, I need DRY principle. – Darama Feb 19 '17 at 11:02
  • There's nothing stopping your from extracting the common logic into a helper method . – nCrazed Feb 19 '17 at 11:52
  • And as Ross suggested, you could return the`$data` array from the controller and let a custom middleware handle conversion to the correct type of response. – nCrazed Feb 19 '17 at 11:56