Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Cache Invalidator Bundle Laravel Package

easytek/doctrine-cache-invalidator-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. 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(),
    
  2. 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'],
                    ],
                ],
            ];
        }
    }
    
  3. 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>
    
  4. Trigger Invalidation: The bundle automatically invalidates caches based on your rules. No manual calls needed.


First Use Case

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.

  1. Define the cache key pattern (product_{id}) and the events (update, delete) in getClasses().
  2. The bundle listens to Doctrine lifecycle events and invalidates the cache automatically.

Implementation Patterns

Workflows

  1. Centralized Cache Invalidation:

    • Define all invalidation rules in a single service (CacheInvalidator).
    • Example for a blog post entity:
      return [
          'App\Entity\Post' => [
              [
                  'cache_id_pattern' => 'post_{slug}_content',
                  'on' => ['update'],
              ],
              [
                  'cache_id_pattern' => 'post_{id}_comments',
                  'on' => ['delete'],
              ],
          ],
      ];
      
  2. Dynamic Cache Keys:

    • Use {attribute} placeholders (like Twig) to dynamically generate cache keys.
    • Example: author_{author.id}_posts invalidates when author.id changes.
  3. Bulk Invalidation:

    • Use * to invalidate on all events (insert, update, delete):
      'on' => ['*'],
      
  4. Multi-Entity Invalidation:

    • Chain invalidations across related entities. Example:
      return [
          'App\Entity\User' => [
              ['cache_id_pattern' => 'user_{id}_profile', 'on' => ['update']],
          ],
          'App\Entity\Profile' => [
              ['cache_id_pattern' => 'profile_{user.id}', 'on' => ['update']],
          ],
      ];
      

Integration Tips

  1. Symfony Cache Integration:

    • Works seamlessly with Symfony’s cache system (e.g., CacheInterface). Ensure your Doctrine entities are properly cached elsewhere (e.g., via DQL RESULT_CACHE or custom services).
  2. Event Listeners:

    • The bundle hooks into Doctrine’s postInsert, postUpdate, and postRemove events. No need to manually subscribe to these events.
  3. Testing:

    • Mock the CacheInvalidationInterface in tests to verify invalidation logic:
      $invalidator = $this->createMock(CacheInvalidationInterface::class);
      $invalidator->method('getClasses')->willReturn([...]);
      $container->set('app.cache_invalidator', $invalidator);
      
  4. Performance:

    • Avoid overly broad invalidation rules (e.g., * for all entities). Prefer granular patterns like post_{id} over all_posts.

Gotchas and Tips

Pitfalls

  1. Archived Package:

    • The package is unmaintained (last release: 2014). Use at your own risk. Consider alternatives like:
      • Symfony’s Cache + manual invalidation.
      • stof/doctrine-extensions for event-driven caching.
      • Custom event subscribers for Doctrine lifecycle events.
  2. Doctrine 2.3+ Limitations:

    • The README mentions missing support for Doctrine 2.3’s wildcard invalidation syntax. This may cause issues with newer Doctrine versions.
  3. Configuration Overrides:

    • The bundle lacks support for defining invalidation rules via configuration (e.g., config/packages/doctrine_cache_invalidator.yaml). You must use a service class.
  4. No Wildcard Support:

    • Patterns like {entity}_* are not supported. Stick to explicit placeholders (e.g., {id}, {slug}).
  5. Cache Provider Assumptions:

    • The bundle assumes a generic cache system. If using Symfony’s cache, ensure your cache keys align with the bundle’s expectations (e.g., no namespacing conflicts).

Debugging

  1. Invalidation Not Triggering:

    • Verify the service is tagged correctly (easytek.doctrine_cache_invalidation).
    • Check Doctrine events are fired (e.g., via postUpdate listeners). Use Symfony’s profiler or dd() in event subscribers.
  2. Cache Keys Not Matching:

    • Debug the generated cache keys by temporarily logging them in your CacheInvalidator:
      public function getClasses(): array {
          $classes = [...];
          error_log(print_r($classes, true)); // Log the rules
          return $classes;
      }
      
  3. Doctrine Version Mismatch:

    • If using Doctrine 2.5+, test thoroughly. The bundle may not support newer features like:
      • MetadataFactory changes.
      • Event system modifications.

Tips

  1. Extend the Bundle:

    • Fork the repository to add missing features (e.g., config-based rules, Doctrine 2.3+ support). Submit a PR if improvements are made.
  2. Combine with Other Tools:

    • Use alongside Symfony’s Cache component for more control:
      $cache = $container->get('cache.app');
      $cache->delete('product_' . $product->getId());
      
  3. Fallback to Manual Invalidation:

    • For critical paths, implement a hybrid approach:
      // In your entity listener
      $cache->delete('product_' . $product->getId());
      // Let the bundle handle other cases
      
  4. Document Your Rules:

    • Add comments to 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
              ],
          ],
      ];
      
  5. Test Edge Cases:

    • Test invalidation with:
      • Null attributes (e.g., {author} where author is null).
      • Complex object graphs (e.g., nested entities).
      • Bulk operations (e.g., EntityManager::flush()).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours