Caching queries without touching the handlers
In most PHP projects, cache logic ends up scattered across business code. The handler that executes the query also contains the caching logic: key generation, lookup, storage, TTL. Two responsibilities, cache code and business code, coexist in the same method.
In Phexium, the decision to cache a query is made in the Query itself. It implements CacheableQueryInterface and declares its TTL. The handler has no idea the cache exists.
final readonly class ListBooksQuery implements CacheableQueryInterface
{
public function getCacheTtl(): int
{
return 60;
}
}
The CachedQueryBus is a decorator of QueryBusInterface. It checks whether the incoming query implements the interface. If so, it generates a cache key from the query properties, then handles the hit/miss cycle. If not, it passes the query through to the inner bus without intervening.
The handler remains identical whether caching is active or not. Adding cache to an existing query comes down to changing the implemented interface and adding a getCacheTtl() method. Removing it means switching back to QueryInterface.
The wiring in the DI container is a single line: decorate the SyncQueryBus with the CachedQueryBus.