Skip to content

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 (readonly class)
  • 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:

  1. Validate command type with TypeGuard
  2. Create/reconstitute domain entities
  3. Persist via repository
  4. 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: CreateBookCommandCreateBookHandler.

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