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:
- Validate query type with
TypeGuard - Fetch data from repository
- Transform to primitive values
- Return response
Dispatching
$query = new ListBooksQuery();
$response = $this->queryBus->dispatch($query);
$viewModel = $this->presenter->present($response)->getViewModel();
Handlers are resolved by naming convention: ListBooksQuery → ListBooksHandler.
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
- CQRS - Conceptual foundation
- Bus Mode - Architectural context
- Query Bus - Dispatching mechanism
- Presenters - Transform query response to ViewModel