| name | acc-create-action |
| description | Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests. |
Action Generator
Generate ADR-compliant Action classes for HTTP endpoints.
Action Characteristics
- Single Responsibility: One action = one HTTP endpoint
- Input Parsing: Collects and parses request input
- Domain Invocation: Calls UseCase/Handler
- Response Delegation: Passes result to Responder
- No Business Logic: Thin coordination layer
- Invokable: Single
__invoke() method
Template
<?php
declare(strict_types=1);
namespace Presentation\Api\{Context}\{Action};
use Application\{Context}\UseCase\{Action}\{Action}Command;
use Application\{Context}\UseCase\{Action}\{Action}Handler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class {Action}Action
{
public function __construct(
private {Action}Handler $handler,
private {Action}Responder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
{inputParsing}
$command = new {Action}Command(
{commandProperties}
);
$result = $this->handler->handle($command);
return $this->responder->respond($result);
}
{privateMethods}
}
Test Template
<?php
declare(strict_types=1);
namespace Tests\Unit\Presentation\Api\{Context}\{Action};
use Application\{Context}\UseCase\{Action}\{Action}Command;
use Application\{Context}\UseCase\{Action}\{Action}Handler;
use Application\{Context}\UseCase\{Action}\{Action}Result;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use Presentation\Api\{Context}\{Action}\{Action}Action;
use Presentation\Api\{Context}\{Action}\{};
\\\;
\\\;
\\\;
()
({}::)
{Action}ActionTest TestCase
{
{Action}Handler ;
{Action}Responder ;
{Action}Action ;
{
->handler = ->({Action}::);
->responder = ->({Action}::);
->action = {Action}(->handler, ->responder);
}
{
= ->([{testData}]);
= ->({Action}::);
= ->(::);
->handler
->(->())
->()
->(->(fn ({Action}Command ) =>
{commandAssertions}
))
->();
->responder
->(->())
->()
->()
->();
= (->action)();
::(, );
}
{
= ->(::);
= ->(::);
->()->();
->()->();
;
}
}
Action Patterns by HTTP Method
GET (Read Single)
<?php
declare(strict_types=1);
namespace Presentation\Api\User\GetById;
use Application\User\UseCase\GetUserById\GetUserByIdQuery;
use Application\User\UseCase\GetUserById\GetUserByIdHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class GetUserByIdAction
{
public function __construct(
private GetUserByIdHandler $handler,
private GetUserByIdResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$userId = $request->getAttribute('id');
= (userId: );
= ->handler->();
->responder->();
}
}
GET (List with Pagination)
<?php
declare(strict_types=1);
namespace Presentation\Api\User\ListAll;
use Application\User\UseCase\ListUsers\ListUsersQuery;
use Application\User\UseCase\ListUsers\ListUsersHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class ListUsersAction
{
public function __construct(
private ListUsersHandler $handler,
private ListUsersResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$queryParams = $request->getQueryParams();
$query = (
page: () ([] ?? ),
perPage: () ([] ?? ),
search: [] ?? ,
);
= ->handler->();
->responder->();
}
}
POST (Create)
<?php
declare(strict_types=1);
namespace Presentation\Api\User\Create;
use Application\User\UseCase\CreateUser\CreateUserCommand;
use Application\User\UseCase\CreateUser\CreateUserHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class CreateUserAction
{
public function __construct(
private CreateUserHandler $handler,
private CreateUserResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$body = (array) $request->getParsedBody();
= (
email: [] ?? ,
name: [] ?? ,
);
= ->handler->();
->responder->();
}
}
PUT/PATCH (Update)
<?php
declare(strict_types=1);
namespace Presentation\Api\User\Update;
use Application\User\UseCase\UpdateUser\UpdateUserCommand;
use Application\User\UseCase\UpdateUser\UpdateUserHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class UpdateUserAction
{
public function __construct(
private UpdateUserHandler $handler,
private UpdateUserResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$userId = $request->getAttribute('id');
= () ->();
= (
userId: ,
name: [] ?? ,
email: [] ?? ,
);
= ->handler->();
->responder->();
}
}
DELETE
<?php
declare(strict_types=1);
namespace Presentation\Api\User\Delete;
use Application\User\UseCase\DeleteUser\DeleteUserCommand;
use Application\User\UseCase\DeleteUser\DeleteUserHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class DeleteUserAction
{
public function __construct(
private DeleteUserHandler $handler,
private DeleteUserResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$userId = $request->getAttribute('id');
= (userId: );
= ->handler->();
->responder->();
}
}
File Placement
| Component | Path |
|---|
| Action | src/Presentation/Api/{Context}/{Action}/{Action}Action.php |
| Action Interface | src/Presentation/Shared/Action/ActionInterface.php |
| Test | tests/Unit/Presentation/Api/{Context}/{Action}/{Action}ActionTest.php |
Generation Instructions
When asked to create an Action:
- Identify HTTP method (GET, POST, PUT, DELETE)
- Determine input source (body, query params, route attributes)
- Identify Command/Query DTO (what to pass to handler)
- Generate Action class with proper namespace
- Generate test with mocked dependencies
Naming Conventions
| HTTP Method | Action Name | Command/Query |
|---|
| GET (single) | Get{Resource}ByIdAction | Get{Resource}ByIdQuery |
| GET (list) | List{Resource}sAction | List{Resource}sQuery |
| POST | Create{Resource}Action | Create{Resource}Command |
| PUT | Update{Resource}Action | Update{Resource}Command |
| PATCH | Patch{Resource}Action | Patch{Resource}Command |
| DELETE | Delete{Resource}Action | Delete{Resource}Command |
References
For detailed patterns and examples:
references/templates.md — Additional Action templates
references/examples.md — Real-world Action examples