A controller returning either a view or JSON depending on the request ends up with the same conditional in every action, and the decision has nothing to do with the action.
class OrderResponse implements Responsable
{
private $order;
public function __construct(Order $order)
{
$this->order = $order;
}
public function toResponse($request)
{
return $request->expectsJson()
? response()->json($this->order)
: view('orders.show', ['order' => $this->order]);
}
}
public function show(Order $order)
{
return new OrderResponse($order);
}
The controller returns an object and the framework asks it for a response, which moves the branch somewhere it can be tested on its own and reused by three actions. It composes with the renderable exception from the same release: both are the framework accepting something that knows how to become a response, rather than requiring one.