25

I want to be able to get the nid but the only information I have is http://example.com/this-is-the-alias.

Is there a way to get either the internal path of /node/* for that alias if I am not on the page? Or is there a way to just get the nid from that alias right away?

0

5 Answers 5

37

I'm not sure if there's a direct function, but one route is to use the path alias manager service to lookup the internal path then regex it for a valid node id to perform an object load on:

$path = \Drupal::service('path.alias_manager')->getPathByAlias('/this-is-the-alias');

if (preg_match('/node\/(\d+)/', $path, $matches)) {
  $node = \Drupal\node\Entity\Node::load($matches[1]);
}

Drupal 9

In Drupal 9 the service has been renamed.

$path = \Drupal::service('path_alias.manager')->getPathByAlias('/this-is-the-alias');
2
  • 4
    For some reason, $path is sometimes equal to /this-is-the-alias. Once was when the root path (node/{id}) was another alias #migrationstruggles, but it was also present with other aliases. Commented Feb 23, 2018 at 2:28
  • 2
    Please remember, if you are using Drupal 8 with translated pages, you need to inform the language in the second parameter: $path = \Drupal::service('path.alias_manager')->getPathByAlias('/this-is-the-alias', $langcode); Commented Mar 21, 2021 at 1:27
14

You can use the following code to get and load an entity and have access to its values.

  use \Drupal\Core\Url;

  $alias = \Drupal::service('path.alias_manager')->getPathByAlias('/etapes-de-la-vie');

  $params = Url::fromUri("internal:" . $alias)->getRouteParameters();
  $entity_type = key($params);
  $node = \Drupal::entityTypeManager()->getStorage($entity_type)->load($params[$entity_type]);
  //to use dpm you need the devel module
  dpm($node->nid->value);

References

1
  • You don't need to resolve the alias, just feed the relative URL into the Url::fromUserInput and then call the getRouteParameters Commented Mar 18, 2021 at 12:06
3

Install the devel module and then use the devel toolbar item Current route info.

This results in this url, which you can type in directly and provide any path known to your drupal installation as query parameter:

/devel/routes/item?path=alias

When it is a node you find the node id in the raw parameters at the end of the listed route variables.

0

This is what I do, so you avoid direct regexs.

$parsed_url = UrlHelper::parse($alias);
$path = \Drupal::service('path_alias.manager')->getPathByAlias($parsed_url['path']);
$params = Url::fromUserInput($path)->getRouteParameters();
$entity_type_id = array_key_first($params);
$entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($params[$entity_type_id]);

0

Beware of the language.

$language = preg_replace('/^\/([^\/]*)\/.*/', '${1}', $newsrc);
$newsrc = preg_replace('/^\/[^\/]*(\/.*)/', '${1}', $newsrc);

$path = \Drupal::service('path_alias.manager')->getPathByAlias($newsrc, $language);
$url = \Drupal\Core\Url::fromUserInput($path, ['language' => $language]);
$params = $url->getRouteParameters();
$entity_type_id = array_key_first($params);

especially if you're running the code inside a drush script. $language should be the language of the target link and $src should be stripped from the language prefix.

If you just want to know if there is a valid internal page

$route_match = \Drupal::service('router.no_access_checks')->match($path);
if ($route_match !== \Drupal\Core\Routing::RouteMatchInterface::NO_ROUTE) {
// do something
}

This can be tricky to discover since it works without stripping the prefix AND without passing $language for English (or probably the default or fallback language).

There should be something buried in Symphony or Drupal code that does all this more elegantly but I haven't been able to discover it. Somehow "normal" routing already does all this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.