The first thing that started getting me interested in a new way of emitting responses was listening to talks on hexagonal architecture. Essentially, having methods on a listener that would call a success method or a failure method. The idea of having dedicated functions for building success and failure cases really stuck for me… But, the implementations all seemed a bit cumbersome to use and usually just moved logic around in the same class. I shoved it to the side.
Next, I was digging around in the source code for Ember and started really messing with the Serializers that it included. Basically, it allowed Ember to have its own parameter language and then provide a very thin translation layer for swapping out data with third party APIs. I tried implementing this with some controller magic a few different times, but it was hard to get out of the conventions.
The third thing that got me interested was reading Paul Jones' article on the Action Domain Responder pattern. I had already been extracting my domain logic to gateways, repositories, and other OOP patterns that made my controllers very thin. But, what interested me was the idea of a responder. A full class that once I give it the data it needs, it will go and build my response, and return the prepared headers and more. This was starting to really get me interested, but having classes for every action within every resource made the code base a bit larger than I really wanted.
The final nail in the coffin that allowed me to make responders that I loved, was Laravel 4.3's controller action injection. This means that while my domain handlers can be injected at the controller class level, things like my request handlers and responders can be injected at a action level. I mixed this with Phil Sturgeon's Fractal to get really customizable responses from my APIs. So, my controller for a resource now looks a bit like this:
Class Users extends Controller
{
protected $userRepo;
public function __construct(UserRepo $user)
{
$this->user = $user;
}
public function index(IndexRequest $request, UserResponder $responder)
{
if ($user = $this->user->paginate($request->perPage)) {
return $responder->successCollectionResponse($user);
} else {
return $responder->failureCollectionResponse();
}
}
public function show($id, ShowRequest $request, UserResponder $responder))
{
if ($user = $this->user->find($id)) {
return $responder->successItemResponse($user);
} else {
return $responder->failureItemResponse();
}
}
}
Then in my responder I can call out to Fractal, build my status codes, append meta data, and do things that muddy up controllers, while having it in a maintainable OOP set of code.
Right now, I share a responder for my different actions, and while this means that I could inject the responder in the controller, I choose to keep it injected to the action so that I can change my responder for a particular action without changing it for every action in a resource.
Also, cool to note is that when you need to add meta data to an API response, you don't have to dig through your controller and worry about messing up any of that code, you just jump in the responder or transformer, make the changes to the response format and that's it!