Laravel 5.5 Responsable Interface for Responses
Published on by Paul Redmond
A new return type will be supported in Laravel 5.5 routes: the Responsable
interface. This contract allows objects to be converted to an HTTP response instance when returned from a controller or route closure. A Responsable
object needs to implement a toResponse()
method which represents the object as an HTTP response.
<?php use Illuminate\Contracts\Support\Responsable; class ExampleObject implements Responsable{ public function __construct($name = null) { $this->name = $name ?? 'Teapot'; } public function status() { switch(strtolower($this->name)) { case 'teapot': return 418; default: return 200; } } public function toResponse() { return response( "Hello {$this->name}", $this->status(), ['X-Person' => $this->name] ); }}
Using the ExampleObject
in a route, you can now do something like this:
Route::get('/hello', function () { return new ExampleObject(request('name'));});
In the framework, the Router class now checks for this type when preparing the response:
if ($response instanceof Responsable) { $response = $response->toResponse();}
Let’s say you have various response types in the App\Http\Responses
namespace to organize your responses. One example might look like this to support a Posts
model:
<?php namespace App\Http\Responses; class PostIndexResponse extends Response{ public function __construct($posts) { $this->posts = $posts; } public function toResponse() { return response()->json($this->transformPosts()); } protected function transformPosts() { return $this->posts->map(function ($post) { return [ 'title' => $post->title, 'description' => $post->description, 'body' => $post->body, 'published_date' => $post->published_at->toIso8601String(), 'created' => $post->created_at->toIso8601String(), ]; }); }}
This is a basic example that illustrates a simple use-case. It returns a JSON response, but you might want the response layer include additional functionality like content negotiation. The example above also assumes an App\Http\Responses\Response
class that could provide some base functionality. The response layer could also contain transformation code like Fractal instead of using it directly in the controller.
A controller that works with the PostsIndexResponse
might look like the following:
<?php namespace App\Http\Controllers; use App\Http\Responses; class PostsController extends Controller{ public function index() { $posts = \App\Post::all(); return new Responses\PostIndexResponse($posts); }}
Check out the commit implementing this contract. While simple, I think it will be interesting to see how people will use Responsable
in Laravel 5.5.