Commands & Handlers
Commands represent intentions to change state. They are part of the CQRS pattern implemented in Phexium's Bus Mode.
Commands
Commands are immutable data objects carrying all information needed for a write operation.
final readonly class CreateBookCommand implements CommandInterface
{
public function __construct(
public IdInterface $id,
public string $title,
public string $author,
public string $isbn
) {}
}
Characteristics:
- Immutable (
readonlyclass) - Named imperatively: verb + noun (e.g.,
CreateBookCommand) - Self-contained with all required data
- Handlers return
void
Handlers
Each command has exactly one handler that executes the business logic:
public function handle(CommandInterface $command): void
{
$book = new Book(
$command->id,
Title::fromString($command->title),
Author::fromString($command->author),
ISBN::fromString($command->isbn)
);
$this->bookRepository->save($book);
$this->eventBus->dispatch(new BookCreatedEvent(
occurredOn: $this->clock->now(),
book: $book,
));
}
Handler responsibilities:
- Validate command type with
TypeGuard - Create/reconstitute domain entities
- Persist via repository
- Dispatch domain events
Type validation:
use Phexium\Domain\TypeGuard;
public function handle(CommandInterface $command): void
{
TypeGuard::that($command)->isInstanceOf(CreateBookCommand::class);
// ...
}
TypeGuard throws InvalidArgumentException if the type doesn't match, ensuring validation is active in production (unlike assert() which can be disabled).
Dispatching
$command = new CreateBookCommand($id, $title, $author, $isbn);
$this->commandBus->dispatch($command);
Handlers are resolved by naming convention: CreateBookCommand → CreateBookHandler.
Best Practices
- Keep commands immutable
- Include all necessary data in the command
- Dispatch events after successful persistence
- Don't return values (use queries for reads)
See Also
- CQRS - Conceptual foundation
- Bus Mode - Architectural context
- Command Bus - Dispatching mechanism
- Event Bus - Event dispatching from handlers
- Domain Events - Events dispatched after persistence