TetherPHP

What is ADR?

Action - Domain - Responder

ADR is a design pattern that separates the concerns of handling requests, executing business logic, and returning responses.

Unlike MVC, which was originally designed for desktop applications, ADR is designed for the web.

In ADR, the Action handles the incoming request, the Domain contains the business logic, and the Responder formats the response.

ADR Example

Here, a user makes a GET request to the route /path.

web.php

$router->get('/path', PathAction::class);

When making a GET request to this route, the action is invoked.

app/Actions/PathAction.php

namespace Actions;

use Domains\PathDomain;
use Responders\PathResponder as Responder;
use TetherPHP\Core\Requests\Request;

class PathAction extends Action
{
    public PathDomain $domain;

    public function __construct(protected Request $request)
    {
        $this->responder = new Responder($request);
        $this->domain = new PathDomain();
    }

    public function __invoke()
    {
        return ($this->responder)($this->domain->getData());
    }
}

In this example, you will notice the Action only has one purpose, which is to take the Domain logic and pass it to the Responder.

app/Domains/PathDomain.php

namespace Domains;

use DTOs\PathDTO;

class PathDomain extends Domain
{
    public function getData(): PathDTO
    {
        $dto = new PathDTO();
        $dto->name = 'Path Domain';
        $dto->description = 'This domain handles all the business logic.';

        return $dto;
    }
}

The Domain is where the business logic exists, in this example we create a new DTO (Data Transfer Object) and return it.

app/Responders/PathResponder.php

namespace Responders;

use DTOs\PathDTO;

class PathResponder extends Responder
{
    public function __invoke(PathDTO $data): string
    {
        return $this->response()->view('path.to.view', [
            'name' => $data->name,
            'description' => $data->description,
        ]);
    }
}

The Responder only returns HTML or JSON. In this example, the Responder was passed the DTO from the Action. The data is sent to the View for rendering.