Using the URL alias UI to change aliases doesn't do necessary invalidations: path aliases don't have cache tags

Created on 29 April 2015, almost 10 years ago
Updated 9 January 2025, about 2 months ago

Problem/Motivation

Quoting @effulgentsia in #2335661-23: Outbound path & route processors must specify cacheability metadata :

See also #2417793-46: Allow entity: URIs to be entered in link fields , where changes to URL aliases don't result in a cache clear of rendered entities containing formatted links. Maybe that needs its own issue, but seems highly related to this, so just noting it here for now.

Reply by @Wim Leers in #2335661-98: Outbound path & route processors must specify cacheability metadata :

This is exactly what I feared was the case. Note that when changing the URL alias of a node, the node updates a MenuLinkContent entity. Which means everything is updated correctly. It is only when updating URL aliases via /admin/config/search/path, that no invalidation happens. But, to be honest, that's really a problem independent of this issue: URL aliases don't track changes and hence also not invalidations in any way. This issue is about fixing the more general problem, that sits a level higher: to make it possible for those outbound path/route processors that do have cacheability metadata, to be able to associate that cacheability with generated URLs.
So we should fix URL aliases in a separate issue.

This is that separate issue.

Proposed resolution

As written in #12:

Remaining tasks

Do it.

User interface changes

None.

API changes

None.

🐛 Bug report
Status

Active

Version

11.0 🔥

Component

path.module

Created by

🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇩🇪Germany ammaletu Bonn, Germany

    This is still happening in Drupal 10.2, and it is hard to justify to customers why they have to save a content or clear the complete cache when they create or change a URL alias through the alias admin page.

    It seems to me that having a cache tag like "node:42:path_alias" would be nice. This should be used whenever the URL of a content is used anywhere, even if there is no path alias yet. Whenever a path alias for this content is touched (newly created, altered, deleted) this cache tag could be invalidated.

    As a remedy for now, I implemented three hooks hook_entity_insert, hook_entity_update, and hook_entity_delete in a module. I check $entity instanceof PathAliasInterface and if yes, then call a method which checks the path and tries to guess the correct cache tag to invalidate. Not perfect, but works for the common cases of node and group content URLs.

    /**
     * Implements hook_entity_insert().
     */
    function my_module_entity_insert(\Drupal\Core\Entity\EntityInterface $entity): void {
      if ($entity instanceof \Drupal\path_alias\PathAliasInterface) {
        invalidateCacheForPath($entity->getPath());
      }
    }
    
    function invalidateCacheForPath(string $path): void {
        // Try to guess the correct cache tag.
        $cacheTag = '';
        $matches = [];
        if (preg_match('@^/([a-z_-]+)/(\d+)$@', $path, $matches) && count($matches) === 3) {
          // Handle the default case of a URL like '/entity_type/id'.
          $cacheTag = "{$matches[1]}:{$matches[2]}";
        }
        elseif (preg_match('@^/group/\d+/content/(\d+)$@', $path, $matches) && count($matches) === 2) {
          // Handle the special case of group content.
          $cacheTag = "group_content:{$matches[1]}";
        }
    
        // Invalidate this cache tag.
        if ($cacheTag) {
          \Drupal::service('cache_tags.invalidator')->invalidateTags([$cacheTag]);
        }
    }
    
  • 🇬🇧United Kingdom joachim

    Came here from 🐛 AliasPathProcessor doesn't add cacheability for the path alias entity Active .

    > find the route name + params associated with the source path (=== "run routing")
    > get the set of cache tags from the route params

    We need to do that for both the old alias path and the new path. Consider this scenario:

    1. Create a node, and give it a path alias, e.g. /foo.
    2. Create a second node, and note its system path
    3. Go to admin/config/search/path, and find the alias entity for path /foo.
    4. Edit the alias entity, and set its system path to point to the 2nd node instead of the first node.

    Both nodes need to have their cache tags invalidated.

    > if empty set of cache tags: invalidate 'rendered' cache tag

    That was the solution I thought of too.

    When we change a path alias inside a node edit form, the node form is taking care of knowing which cache tags should be invalidated, so we're fine.

    In the URL alias admin UI, we don't have that context.

    There is also the case where APIs change URL aliases -- e.g. JSONAPI, or Entity Share module. We should document on the PathAlias entity class that if you are saving path aliases yourself, you either need to know what to invalidate, or to invalidate the 'rendered' cache tag to be sure.

  • 🇬🇧United Kingdom catch

    I think invalidating the rendered cache tag from the path alias UI should be OK - that page is rarely used so it should be infrequent.

    Trying to add cache tags to rendered content from specific path aliases, and handling unaliased paths getting an alias etc. would explode the number of cache tags and invalidations, so potentially clearing more than we need to via 'rendered' seems like it would be better overall, less precise but a lot lighter.

Production build 0.71.5 2024