Skip to content

Responder

Michał Golon edited this page Jul 27, 2018 · 3 revisions

Responder in ADR is responsible for building the response. Responder's constructor method should collect all required data needed for creating a response.

class ShowUserActionResponder implements ResponderInterface
{
    /**
     * @var mixed
     */
    protected $data;
    
    public function __construct($data)
    {
        $this->data = $data;
    }

    /**
     * @return Response
     */
    public function respond(): Response
    {
        return new Response(view('users.show', $this->data))
    }
}

Any responder must implement ResponderInterface interface.

Content negotiation

One of the additional responsibilities of the responder might be the content negotiation.

Small handy mechanism was added to handle content negotiation in an easy way. It is recommended for the responder to extend HydrefLab\Laravel\ADR\Responder\Responder abstract class. This class adds/uses functionality for determining the response's format as well as provides two default methods for building most popular response types: html and json.

HydrefLab\Laravel\ADR\Responder\Responder class contains mapping between format required by the client and the method that should be called depending on that format.

If there is a need, developer can implement content negotiation mechanism on its own, using HydrefLab\Laravel\ADR\Responder\Responder class as a reference.

Middlewares

An action in ADR can handle requests of different origin - API ones, typical web ones, etc. This fact introduces small inconvenience related to the middleware. There can be a different set of middlewares for API-like requests and a different set for web-like requests. This is especially the case with web and api middleware groups in Laravel, that are assigned to route groups by default.

Question is: how to handle that?

There are few solutions, but one requires to edit all middlewares, another extends Laravel core a bit too much, yet another does too much stuff behind the scenes. In order to have simple and clean solution and not to lose middleware grouping functionality, an action class should register all middlewares (groups and route ones) inside __construct() method. Of course, if there are some common middlewares, they can be registered either as global ones or attached to route group. Unfortunately, web and api middleware groups have to be removed from RouteServiceProvider.

Is that differ from Laravel's approach? No. Is that less convenient? Yes.

Enabling default middleware

App\Http\Actions\Action class adds mechanism to set default middleware groups (web and api) based on request type. However, setting default middleware group is disabled by default. It can be enabled for a particular action or globally (or enabled globally, but disabled for a particular action).

To enable default middleware groups for actions globally, in RouteServiceProvider::boot() add

Route::applyDefaultAdrMiddleware();

App\Http\Actions\Action class contains also $applyDefaultMiddleware property. With that, developer can enable/disable default middleware group for a particular action.

namespace App\Http\Actions;

class Action
{
    protected $setDefaultMiddleware = null; // do not change here
    
    // ...
}
namespace App\Http\Actions;

class MyCustomAction extends Action
{
    protected $setDefaultMiddleware = true;
    
    // ...
}

Class property takes precedence over global configuration.

Clone this wiki locally