easytek/doctrine-cache-invalidator-bundle
Installation:
composer require "easytek/doctrine-cache-invalidator-bundle" "dev-master"
Add the bundle to your AppKernel.php (or bundles.php in Symfony 4+):
new Easytek\DoctrineCacheInvalidatorBundle\EasytekDoctrineCacheInvalidatorBundle(),
Define a Custom Invalidation Service:
Create a service implementing CacheInvalidationInterface:
namespace App\Cache;
use Easytek\DoctrineCacheInvalidatorBundle\Cache\CacheInvalidationInterface;
class CacheInvalidator implements CacheInvalidationInterface
{
public function getClasses(): array
{
return [
'App\Entity\Product' => [
[
'cache_id_pattern' => 'product_{id}',
'on' => ['update', 'delete'],
],
],
];
}
}
Register the Service:
In config/services.yaml (Symfony 4+):
services:
App\Cache\CacheInvalidator:
tags:
- { name: easytek.doctrine_cache_invalidation }
Or in services.xml (Symfony 3):
<service id="app.cache_invalidator" class="App\Cache\CacheInvalidator">
<tag name="easytek.doctrine_cache_invalidation" />
</service>
Trigger Invalidation: The bundle automatically invalidates caches based on your rules. No manual calls needed.
Scenario: You cache product details in a custom cache (e.g., Redis, APC) and want to invalidate it when a product is updated or deleted.
product_{id}) and the events (update, delete) in getClasses().Centralized Cache Invalidation:
CacheInvalidator).return [
'App\Entity\Post' => [
[
'cache_id_pattern' => 'post_{slug}_content',
'on' => ['update'],
],
[
'cache_id_pattern' => 'post_{id}_comments',
'on' => ['delete'],
],
],
];
Dynamic Cache Keys:
{attribute} placeholders (like Twig) to dynamically generate cache keys.author_{author.id}_posts invalidates when author.id changes.Bulk Invalidation:
* to invalidate on all events (insert, update, delete):
'on' => ['*'],
Multi-Entity Invalidation:
return [
'App\Entity\User' => [
['cache_id_pattern' => 'user_{id}_profile', 'on' => ['update']],
],
'App\Entity\Profile' => [
['cache_id_pattern' => 'profile_{user.id}', 'on' => ['update']],
],
];
Symfony Cache Integration:
CacheInterface). Ensure your Doctrine entities are properly cached elsewhere (e.g., via DQL RESULT_CACHE or custom services).Event Listeners:
postInsert, postUpdate, and postRemove events. No need to manually subscribe to these events.Testing:
CacheInvalidationInterface in tests to verify invalidation logic:
$invalidator = $this->createMock(CacheInvalidationInterface::class);
$invalidator->method('getClasses')->willReturn([...]);
$container->set('app.cache_invalidator', $invalidator);
Performance:
* for all entities). Prefer granular patterns like post_{id} over all_posts.Archived Package:
Cache + manual invalidation.stof/doctrine-extensions for event-driven caching.Doctrine 2.3+ Limitations:
Configuration Overrides:
config/packages/doctrine_cache_invalidator.yaml). You must use a service class.No Wildcard Support:
{entity}_* are not supported. Stick to explicit placeholders (e.g., {id}, {slug}).Cache Provider Assumptions:
Invalidation Not Triggering:
easytek.doctrine_cache_invalidation).postUpdate listeners). Use Symfony’s profiler or dd() in event subscribers.Cache Keys Not Matching:
CacheInvalidator:
public function getClasses(): array {
$classes = [...];
error_log(print_r($classes, true)); // Log the rules
return $classes;
}
Doctrine Version Mismatch:
MetadataFactory changes.Extend the Bundle:
Combine with Other Tools:
Cache component for more control:
$cache = $container->get('cache.app');
$cache->delete('product_' . $product->getId());
Fallback to Manual Invalidation:
// In your entity listener
$cache->delete('product_' . $product->getId());
// Let the bundle handle other cases
Document Your Rules:
getClasses() to explain cache key patterns and invalidation triggers:
return [
'App\Entity\Product' => [
[
'cache_id_pattern' => 'product_{id}_details', // Used by ProductDetailController
'on' => ['update'], // Invalidate on product updates only
],
],
];
Test Edge Cases:
{author} where author is null).EntityManager::flush()).How can I help you explore Laravel packages today?