How I do it :
# routes.php
$router->pattern('format', '.json|.csv|.whatever');
$router->get('auctions/{id}/{format?}', ['uses' => 'AuctionsController@show']);
# AuctionsController.php
public function show($id, $format = null)
{
$auction = Auction::findOrFail($id);
if($format == '.json') return $auction;
return view('auctions.show', ['auction' => $auction]);
}
When I get many format and get fedup with the if statements everywhere I register a special response macro in a service provider :
# AppServiceProvider.php
public function register()
{
$this->app->call([$this, 'registerResponseMacros']);
}
public function registerResponseMacros(Request $request, ResponseFactory $response)
{
$response->macro('format', function($format, $resource, $default = null) use($request, $response)
{
if($format == '.json' or $request->wantsJson()) return $response->json($resource);
if($format == '.csv') return $response->file($resource);
return $default;
});
$response->macro('file', function(DownloadableInterface $downloadable) use($response)
{
$file_name = $downloadable->getDownloadFileName();
$file_path = $downloadable->getDownloadFilePath();
return $response->download($file_path, $file_name);
});
}
This way I can only use one line for the response :
public function show($id, $format = null)
{
$auction = Auction::findOrFail($id);
return response()->format($format, $auction, view('auctions.show', [
'auction' => $auction
]);
}
First arg the desired format, second arg the data to format, third arg the default response.
But I think it would be cool if laravel request object had special features to handle the format. Something like a special token in the route pattern, which is not passed to the action's arguments and we can retrieve with something like $request->getFormat().