Published July 26, 2017

The new Responsable interface in Laravel is really awesome, it allows us to simplify our controllers with custom responses objects.

But one of the complexity with responses is the content negotiation and the new feature doesn’t help us on this. How could we solve this problem?

The new feature

First, let’s look at how Laravel uses the Responsable interface in the Router.

The only method on the Respondable interface is the toResponse method. Then, if the response is Jsonable or something similar, Laravel will use the JsonResponse which json_encode all the data.

Adding Content Negotiation

There is no sign of Content-Negotiation in this method. So if I need to build a response in JSON or in HTML depending of the type the request, I will have some conditions in my controller:

Not too bad, thanks to the awesome wantsJson() method, but it could be better (especially if my controller is not a simple database query):

Better! Now let’s dive in the UsersResponse:

Avoiding conditionals with polymorphism

It’s often a good thing to replace conditionals by polymorphism. I would rather prefer this response with a new NegociateContent trait:

Or this one which extends a new BaseResponse:

The NegociateContent or the BaseResponse implementations are really straightforward. We can add more checks and content type if needed of course.

Let’s try to build the same view helper as in mailables

We can even simplify the toHtmlResponse method with the same concept as in Mailable. As you may know, in mailables, all public properties are directly accessible in the mail view.

I stole this code from the Illuminate\Mail\Mailable class in the framework (I just refactored it to collections).


I think these few lines of code really improve the Responsable interface. I really like the Mailable reflection as it feels really natural to me.

I may try to pull request the framework to add these features if people like them so don’t hesitate to send me a message on Twitter @ThibaudDauce or by mail ( to tell me what you think!