Skip to content

Queries & Handlers

Queries request data without modifying state. They are part of the CQRS pattern in Phexium's Bus Mode.

Queries

Queries define what data is requested and any filtering criteria:

final class ListBooksQuery implements QueryInterface {}

final readonly class DetailBookQuery implements QueryInterface
{
    public function __construct(public string $bookId) {}
}

Characteristics:

  • Immutable
  • Named: verb + noun + Query (e.g., ListBooksQuery)
  • May contain filters
  • No side effects

Handlers

Handlers retrieve data and return QueryResponseInterface objects:

public function handle(QueryInterface $query): QueryResponseInterface
{
    $books = $this->bookRepository->findAll();

    $bookItems = [];
    foreach ($books as $book) {
        $bookItems[] = [
            'id' => $book->getId()->getValue(),
            'title' => $book->getTitle()->getValue(),
            'status' => $book->getStatus()->value,
        ];
    }

    return new ListBooksResponse($bookItems);
}

Handler responsibilities:

  1. Validate query type with TypeGuard
  2. Fetch data from repository
  3. Transform to primitive values
  4. Return response

Dispatching

$query = new ListBooksQuery();
$response = $this->queryBus->dispatch($query);
$viewModel = $this->presenter->present($response)->getViewModel();

Handlers are resolved by naming convention: ListBooksQueryListBooksHandler.

Data Transformation

Transform domain entities to primitives in handlers:

// Do: Return primitives
$bookItems[] = ['id' => $book->getId()->getValue()];

// Don't: Return domain entities
$bookItems[] = $book;  // Leaks domain to presentation

See Also