Make it possible to link to an entity by UUID

Created on 9 October 2014, over 10 years ago
Updated 8 June 2023, almost 2 years ago

Problem/Motivation

It would be great to provide URLs with UUIDs in their so you can link to them.

The solution would need to meet the following requirements:

  • Allow a UUID-based URL to be used in menus, end-user-facing links should use a path alias when available
  • Allow a UUID-based URL to be used for front page, 403 and 404 pages, without strange redirection by-effects
  • Allow a UUID-based URL to be used as in the page condition for e.g. block-placement. It should not make a difference if the alias-, numeric ID- or UUID-based URL is used, the block should be shown regardless of the URL used to access the content
  • The "duplicate content" situation is not made worse then it is, i.e. search engines should be guided to a canonical URL somehow, either by redirects (for aliases and traditional numeric URLs this is handled by Redirect module in contrib) or a canonical metatag

Proposed resolution

The most recent solution uses a path converter. It relies on the existing behaviour of setting the canonical meta tag to avoid duplicate content issues in terms of SEO (because that is already the approach taken with aliases vs. system paths). Internally, the path is converted to the numeric path, so that anything relying on that also works for the UUID-based URL.

Add a new uuid link template for entities:

$node->toUrl('uuid');

Remaining tasks

  • [ ] Resolve #2690747: [PLAN] Create an index of UUIDs โ†’
  • [ ] Adapt path processor that can up-cast an {uuid} anywhere in an URL without needing to know the actual entity type
  • [x] Add special case code to Entity::toUrl() to handle 'uuid'
  • โ“Test all use cases
  • [ ] Update CR

User interface changes

The UUID-based URL is available.

API changes

It is possible to request the UUID-based URL for an entity.

โœจ Feature request
Status

Active

Version

11.0 ๐Ÿ”ฅ

Component
Entityย  โ†’

Last updated about 9 hours ago

  • Maintained by
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom @catch
  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland @berdir
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany @hchonov
Created by

๐Ÿ‡ฉ๐Ÿ‡ชGermany dawehner

Live updates comments and jobs are added and updated live.
  • Contributed project blocker

    It denotes an issue that prevents porting of a contributed project to the stable version of Drupal due to missing APIs, regressions, and so on.

  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

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 c-logemann Frankfurt/M, Germany

    This Issue started with this text by @dawehner:

    > It would be great to provide URLs with UUIDs in their so you can link to them.

    > For poormans menu staging you could use menu_link_config and store refs to UUIDs, like uuid/{entity_type}/{uuid}
    which page does a 301 redirect to the actual entity page.

    I think this issue should stay on focus with the "{entity_type}/{uuid}" plan. Getting the entity_type removed from the urls is interesting but I think this should move to another issue including all the problems and dependencies like #2690747: [PLAN] Create an index of UUIDs โ†’ .

    Because of symfony and ParamConverter etc. there are many possibilities to fix things in contrib. So I just decided to solve things there. At first I will concentrate on user entities (e.g. "uuid/user/{uuid}") because I need a solution where users should not know their serial uid. After doing some tests today I think this is basically not complicated.

    Especially for everything related to nodes, aliases, and redirects things are more complicated. And that's another reason to stay focused on {entity_type} in paths. For me he user part is the most important thing because I don't want to replace the user entity. Since we can create our own entity types with nearly everything a node can do this would be easier. And on the project where I need user/uuid paths I haven't decided yet if I really want to use nodes.

    (I will add a comment here when there is a project I will add my solutions.)

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany DiDebru
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia vsujeetkumar Delhi

    Re-roll patch created for 11.x.

  • last update over 1 year ago
    Custom Commands Failed
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia vsujeetkumar Delhi

    Fixed the CCF issue, Please have a look.

  • last update over 1 year ago
    30,444 pass, 1 fail
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia vsujeetkumar Delhi

    Fixed the failed test cases.

  • last update over 1 year ago
    30,448 pass
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    Thanks @vsujeetkumar for pushing this forward/keeping patch compatible.

    I removed Tasks from issue which are not on focus of this issue:

    • [ ]
    • [ ]
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    I'm currently working on a small symfony only project and discovered that it's possible to define multiple routes on an identical path and tested that Drupal 10.3 is compatible with this. For example this documetation:
    https://symfony.com/doc/current/routing.html#parameters-validation

    I tested the last patch and was wondering why it's working so I found this in the patch code:

    /**
    +   * {@inheritdoc}
    +   */
    +  public function processInbound($path, Request $request) {
    +    $matches = [];
    +    if (preg_match('/^\/([a-z_]+)\/(' . Uuid::VALID_PATTERN . ')$/i', $path, $matches)) {
    +      $entity_type_id = $matches[1];
    +      $uuid = $matches[2];
    +      if ($this->entityTypeManager->hasDefinition($entity_type_id)) {
    +        $storage = $this->entityTypeManager->getStorage($entity_type_id);
    +        $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
    +        if ($entity_type->hasLinkTemplate('canonical') && $entities = $storage->loadByProperties(['uuid' => $uuid])) {
    +          /** @var \Drupal\Core\Entity\EntityInterface $entity */
    +          $entity = reset($entities);
    +          $path = '/' . ltrim($entity->toUrl()->getInternalPath(), '/');
    +        }
    +      }
    +    }
    +    return $path;
    +  }

    It's interesting that it's working but with this solution we loose the benefit of routing information and debugging etc. I like the idea to just disable integer routes in custom code to only use. If just use an entity_uuid param converter it is possible to use the same controllers for all entity paths e.g. "/user/{user}/edit" with a route 'user.uuid_edit'

    I also want to make it possible to avoid user (int) ids in password reset paths where currently {uid} is used. But this maybe something for contrib.

  • Assigned to c-logemann
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    I try to improve in direction of second route as described above.

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    Before I start with coding want to add some additional comments after thinking about two routes which allows several thinks like the described identical scheme which is now possible with symfony.
    Using two route definitions for each involved entity makes it possible to realize many thinks like different access and also different routes. We can also introduce switches to enable uuid Routes of core only if somebody wants. And if somebody want the additional uuid route just as a redirect or with a path pattern like /uuid/user/{uuid}" this can be solved separately in additional code/contrib/custom code etc. So it's possible to solve seo concerns with robots.txt is possible.
    In my personal opinion, it's currently a big disadvantage of Drupal that it's not possible to avoid serial IDs especially for users. At any other place I can avoid this easier e.g with not using node and other core entities. The reason why I want to avoid this that I think this is very important for situations when you run a web application where others should not see how many content entities are generated e.g. users, shop carts, issue tickets, mails etc. This gives competitor organizations and persons too much information not everyone likes to share. This is maybe a reason why companies and other organizations didn't choose Drupal.
    On the the other side brings a uuid only strategy lots of possibilities to export, archive, re-import or import elsewhere of content without dealing with complex redirection data.
    Both areas are my current motivation. Beside users I have already solved everything with custom entities and the wonderful module entity_reference_uuid. But it would be fine to have something more in core like an official uuid param converter. I know Drupal\jsonapi\ParamConverter and maybe start to use this at first.

  • ๐Ÿ‡ฆ๐Ÿ‡ฒArmenia murz Yerevan, Armenia

    By the way, loading entities by UUID is not cached, here is the issue โœจ Add static cache for loadEntityByUuid function to store uuid-id pairs in memory Active

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    @murz Thanks for the input.

  • Issue was unassigned.
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    I did some research of the current code and the actual patch. I still like to have an uuid everywhere strategy including revision routes. But currently the serial id strategy is deep integrated in a dynamical way. So a complete new strategy especially as dual solution ha a high complexity. So I think this should be postponed until there is more interest and some discussion and decision by core maintainers.

    Meanwhile I will solve the user uuid situation in contrib and just created a new project for this: U3ID โ†’ . With the U3ID module I can present a prove of concept and maybe something which can move partially to core in future.

    I will try to test the current patch against the the dual route concept ASAP on patch /user/{user|u3id_user} if there is a conflict which think it will be. Maybe there are other custom solutions out there based on additional routes which can be affected by the PathProcessor solution of the current patch.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance andypost
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany c-logemann Frankfurt/M, Germany

    I created additional routes for /user/{uuid} and /user/{uuid}/edit in the u3id module and published already:
    https://git.drupalcode.org/project/u3id

    1. This is working fine.
    2. The pathprocessing from actual patch makes it impossible for such clean route solution. So I strongly recommend to not commit for core. I currently even not recommend to not move to contrib or with add a warning for risks of breaking other code.

    There are lot's of concerns against a pure uuid strategy as I read here: [1726734]

    For getting forward I suggest to focus on a a minimal improvement:
    1. First of all we should provide an entity_uuid ParamConverter. For u3id I copied of the core jsonapi: ๐Ÿ› Cannot use UUID as entity ID Needs work
    2. Following the initial feature request we can just provide a possibility to access entities based on additional uuid route configurations.
    3. Per default we can just do redirections and introduce settings.php options to change behavior to an entity view.

    Everything else should be postponed for core until there is a larger support for more uuid in core routes. I'm currently fine with my contrib project u3id and already solved the problem of rendering the serial uid in the canonical html link with replacing the entity view controller and use now the uuid path.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    ๐Ÿ› Cannot use UUID as entity ID Needs work just landed. Time to reconsider this? ๐Ÿ˜Š

Production build 0.71.5 2024