From 68f08abf2a31ea2ce399bab0a1c50cf2d47fde06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Delr=C3=A9?= Date: Mon, 11 May 2026 23:13:06 +0200 Subject: [PATCH 1/3] docs(httpcache): document PurgeTagProviderInterface extension point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guillaume Delré --- core/performance.md | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/core/performance.md b/core/performance.md index 2b40a4933d4..bf20218e9ef 100644 --- a/core/performance.md +++ b/core/performance.md @@ -282,6 +282,59 @@ final class UserResourcesSubscriber implements EventSubscriberInterface } ``` +### Invalidating Additional Tags on Mutation + +Implement `ApiPlatform\HttpCache\PurgeTagProviderInterface` to add extra cache tags to invalidate +when an entity is mutated. This is useful for any tags the built-in listener cannot resolve on its +own: sub-resource collection IRIs (e.g. `/parents/{parentId}/children`), surrogate-key prefixes, +class-based tags, or any custom invalidation strategy. + +```php +getParent()) { + return []; + } + + yield '/parents/'.$entity->getParent()->getId().'/children'; + } +} +``` + +#### Symfony + +With [autowiring and autoconfiguration](https://symfony.com/doc/current/service_container/autowiring.html) +enabled (the default), the service is automatically registered. To declare the service explicitly: + +```yaml +# config/services.yaml +services: + App\HttpCache\ChildPurgeTagProvider: + tags: + - name: api_platform.http_cache.purge_tag_provider +``` + +#### Laravel + +Register and tag the implementation in a service provider: + +```php +$this->app->bind(\App\HttpCache\ChildPurgeTagProvider::class); +$this->app->tag( + [\App\HttpCache\ChildPurgeTagProvider::class], + \ApiPlatform\HttpCache\PurgeTagProviderInterface::class +); +``` + ## Setting Custom HTTP Cache Headers The `cacheHeaders` attribute can be used to set custom HTTP cache headers: From 87648d10d2b3e5adb28d2d51287e80b5617a406f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Delr=C3=A9?= Date: Tue, 19 May 2026 15:06:21 +0200 Subject: [PATCH 2/3] docs(httpcache): update PurgeTagProviderInterface example with per-operation methods Replace getTagsForResource() with the three dedicated methods (getTagsForInsert, getTagsForUpdate, getTagsForDelete) and show the parent-change invalidation use case that motivated the split. Drop the Laravel section (out of scope). --- core/performance.md | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/core/performance.md b/core/performance.md index bf20218e9ef..c6d9366d9a9 100644 --- a/core/performance.md +++ b/core/performance.md @@ -285,10 +285,13 @@ final class UserResourcesSubscriber implements EventSubscriberInterface ### Invalidating Additional Tags on Mutation Implement `ApiPlatform\HttpCache\PurgeTagProviderInterface` to add extra cache tags to invalidate -when an entity is mutated. This is useful for any tags the built-in listener cannot resolve on its +when a resource is mutated. This is useful for any tags the built-in listener cannot resolve on its own: sub-resource collection IRIs (e.g. `/parents/{parentId}/children`), surrogate-key prefixes, class-based tags, or any custom invalidation strategy. +The interface provides three methods so you can differentiate between operations and receive the +previous state of the resource on updates: + ```php getParent()) { + return []; + } + + yield '/parents/'.$resource->getParent()->getId().'/children'; + } + + public function getTagsForUpdate(object $resource, object $previousResource): iterable + { + // Invalidate both the old and new parent collection when the parent changes + if ($resource instanceof Child && null !== $resource->getParent()) { + yield '/parents/'.$resource->getParent()->getId().'/children'; + } + + if ($previousResource instanceof Child && null !== $previousResource->getParent()) { + yield '/parents/'.$previousResource->getParent()->getId().'/children'; + } + } + + public function getTagsForDelete(object $resource): iterable { - if (!$entity instanceof Child || null === $entity->getParent()) { + if (!$resource instanceof Child || null === $resource->getParent()) { return []; } - yield '/parents/'.$entity->getParent()->getId().'/children'; + yield '/parents/'.$resource->getParent()->getId().'/children'; } } ``` @@ -323,18 +347,6 @@ services: - name: api_platform.http_cache.purge_tag_provider ``` -#### Laravel - -Register and tag the implementation in a service provider: - -```php -$this->app->bind(\App\HttpCache\ChildPurgeTagProvider::class); -$this->app->tag( - [\App\HttpCache\ChildPurgeTagProvider::class], - \ApiPlatform\HttpCache\PurgeTagProviderInterface::class -); -``` - ## Setting Custom HTTP Cache Headers The `cacheHeaders` attribute can be used to set custom HTTP cache headers: From f597a3b917631e5ae634867c6357880929eb4b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Delr=C3=A9?= Date: Tue, 19 May 2026 15:34:10 +0200 Subject: [PATCH 3/3] docs(httpcache): add Laravel registration section for PurgeTagProviderInterface --- core/performance.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/performance.md b/core/performance.md index c6d9366d9a9..203416b2e3d 100644 --- a/core/performance.md +++ b/core/performance.md @@ -347,6 +347,11 @@ services: - name: api_platform.http_cache.purge_tag_provider ``` +#### Laravel + +Any class implementing `PurgeTagProviderInterface` placed inside your `app/` directory is automatically +discovered and registered by API Platform's autoconfiguration. No further setup is required. + ## Setting Custom HTTP Cache Headers The `cacheHeaders` attribute can be used to set custom HTTP cache headers: