Installation
composer require xlabs/resultcachebundle
Add to config/bundles.php (Symfony) or config/app.php (Laravel via bridge):
return [
// ...
XLabs\ResultCacheBundle\XLabsResultCacheBundle::class => ['all' => true],
];
Configuration
Edit config/packages/xlabs_resultcache.yaml (Symfony) or config/resultcache.php (Laravel):
xlabs_resultcache:
driver: 'doctrine' # or 'apcu', 'memcache', 'redis'
ttl: 3600 # Default TTL in seconds
namespace: 'app.' # Optional namespace prefix
First Use Case Enable caching for a repository query:
// In a Symfony service or Laravel service provider
$entityManager->getRepository(MyEntity::class)
->createQueryBuilder('e')
->enableResultCache(); // Enable caching for this query
Repository-Level Caching
// Symfony
$qb = $em->getRepository(MyEntity::class)->createQueryBuilder('e');
$qb->enableResultCache(); // Cache results for this query
$results = $qb->getQuery()->getResult();
// Laravel (via bridge)
$results = MyEntity::query()
->enableResultCache()
->get();
Dynamic TTL per Query
$qb->enableResultCache(600); // Override default TTL (10 mins)
Cache Invalidation
// Invalidate all cached queries for an entity
$em->getRepository(MyEntity::class)->invalidateResultCache();
// Invalidate specific query (requires unique cache key)
$qb->invalidateResultCache();
XLabs\ResultCacheBundle\Laravel\ResultCacheServiceProvider for seamless Laravel integration.onFlush to invalidate caches before writes:
$em->getEventManager()->addEventListener(
\Doctrine\ORM\Events::onFlush,
function () use ($em) {
$em->getRepository(MyEntity::class)->invalidateResultCache();
}
);
SELECT queries with predictable results (avoid ORDER BY with dynamic columns or LIMIT/OFFSET with large datasets).Cache Key Collisions
WHERE id = ?) may generate the same cache key.->setParameter('id', $id) explicitly and ensure parameters are unique per query.TTL Misconfiguration
ttl: 0 disables caching entirely. Negative values throw exceptions.$ttl = max(1, $ttl); // Ensure minimum TTL of 1 second
Doctrine Proxy Conflicts
->getScalarResult() or ->getSingleScalarResult() for simple queries, or hydrate manually:
$results = $qb->getQuery()->getArrayResult();
Cache Hit/Miss Logging Enable debug mode in config:
xlabs_resultcache:
debug: true
Logs appear in Symfony’s profiler or Laravel’s log channel.
Cache Key Inspection Dump the generated cache key:
$qb->enableResultCache();
$query = $qb->getQuery();
$cacheKey = $query->getCacheKey(); // Inspect key
Custom Cache Drivers
Implement XLabs\ResultCacheBundle\Cache\CacheDriverInterface for custom backends (e.g., DynamoDB):
class DynamoDbDriver implements CacheDriverInterface {
public function get($key) { /* ... */ }
public function set($key, $data, $ttl) { /* ... */ }
public function delete($key) { /* ... */ }
}
Query Filtering
Override XLabs\ResultCacheBundle\Cache\QueryCacheKeyGenerator to exclude queries from caching:
protected function shouldCache(\Doctrine\ORM\QueryBuilder $qb) {
return !$qb->getQuery()->getHint('cacheable', false);
}
Event Listeners Extend cache invalidation logic:
$em->getEventManager()->addEventListener(
\Doctrine\ORM\Events::postUpdate,
function ($event) {
$event->getObject()->getClass()->getRepository()
->invalidateResultCache();
}
);
How can I help you explore Laravel packages today?