44

I have a node object, and I am trying to use it to get a given path in Drupal 8.

There was drupal_lookup_path() in Drupal 7 but I'm not seeing any equivalent or documentation for Drupal 8.

What's the new "Drupal" way to get a path from a node object?

Would it be something simple like $node->get('path')?

This seems like a simple question, but I'm just absolutely not finding any documentation on it.

Notice I do not want the path alias for the current path; I want the path alias for an arbitrary node, given a node object or a node ID.

5
  • 3
    Possible duplicate of Get the current path alias or path?
    – Kevin
    Commented Mar 8, 2017 at 17:06
  • I think this might be a duplicate, check the linked question there are lots of answers.
    – Kevin
    Commented Mar 8, 2017 at 17:07
  • 1
    The other question has answers saying how to get the path alias for the current path, not for a node for which the OP knows the node ID.
    – avpaderno
    Commented Mar 8, 2017 at 17:59
  • It's not a duplicate - I don't want the current path. I want the path given an arbitrary node object or NID.
    – Jack Ryan
    Commented Mar 8, 2017 at 18:03
  • 2
    Yes, this is not a duplicate, see my answer.
    – 4uk4
    Commented Mar 8, 2017 at 19:10

9 Answers 9

87

To get the path for a node id use AliasManager::getAliasByPath:

Drupal 8

$alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$nid);

Drupal 9

$alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'.$nid);

See comment from Felix Eve.

0
41

If you only have the nid, 4k4's solution of

$alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$nid);

Works great. But if you already have a node object you can skip a step or two. Nodes actually have built in methods for getting urls.

$node->toUrl()->toString();

Would return the aliased url of the node.

toUrl() returns a url object. See here https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Url.php/class/Url/8.2.x

and toString() is a method of the url object that returns the string representation of the url.

4
  • 18
    Note that $node->toUrl()->setAbsolute()->toString() will return the absolute URL, useful for sharing etc.
    – Tim
    Commented Nov 18, 2017 at 14:57
  • 4
    Both methods look equivalent at first sight, but there is a difference. Using $node->toUrl() will give you the full path to a node. This means you get the path alias, but other URL manipulations (e.g. adding a language prefix) will also be applied. The getAliasByPath() method, on the other hand, will give you just the path alias. Commented Sep 27, 2021 at 9:46
  • I worry about the language prefix being present, but I prefer this method because it's entity type agnostic. You can pass nodes, terms, media, etc (anything path-able) to it without having to hard code '/node/x'.
    – atwixtor
    Commented May 9 at 20:19
  • @atwixtor – getAliasByPath doesn't give you a language prefix, yes, but when you now put the alias into Url::fromUserInput with a language option you'll get the prefix as well.
    – leymannx
    Commented Oct 16 at 10:54
23

What about using Url:

use Drupal\Core\Url;    

...

$url = Url::fromRoute('entity.node.canonical', ['node' => $nid])->toString();
3
  • 12
    IIRC, the primary difference between this and using the AliasManager, is that this will also ensure that outbound path processors run, while AliasManager just does the alias lookup. You can also get the Url object directly as $node->toUrl().
    – mpdonadio
    Commented Mar 9, 2017 at 0:57
  • 2
    Much better solution.
    – Patrick
    Commented Oct 21, 2017 at 23:35
  • 1
    Broiken if installed in a subdir. Commented Jul 16, 2020 at 5:33
13

Best way to get node URL from node object-

  • Absolute Path : $node->toUrl()->setAbsolute()->toString();
  • Relative Path : $node->toUrl()->toString();

It will also handle node language.

1
  • The question was about the node alias, this is broiken if installed in a subdir. Commented Jul 16, 2020 at 5:33
4

You can also use the load method from path.alias_storage to return an array of the alias details or boolean false if there wasn't a path found for that node.

$aliasArray = \Drupal::service('path.alias_storage')->load(['source' => '/node/' . $nid]);

2
  • Will this load all existing aliases? I would say yes. In my case, I need all aliases. Commented Jun 3, 2021 at 16:42
  • Drupal\Core\Path\AliasStorage is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the "path_alias.repository" service instead, or the entity storage handler for the "path_alias" entity type for CRUD methods.
    – Felix Eve
    Commented Feb 21 at 13:16
3

If you want to get the node alias url by languages dont forget to use the language like this.

$alias_url = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'. $nid, $langcode);

If you are using it in a class do not forget to use the dependencies injection correctly.

2

Surprisingly, as of Drupal 9.2, none of the current answers work in a multilingual site that uses path prefixes for language detection.

This is what I ended up using:

// Note: using dependency injection to get the language code.
$lang_code = $this->languageManager
  ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
  ->getId();

// Note: using dependency injection to load the node.
$test_nid = 1
$test_node = $this->entityTypeManager->getStorage('node')->load($test_nid);

// If the node has a translation, load it.
if ($test_node->hasTranslation($lang_code)) {
  $test_node = $test_node->getTranslation($lang_code);
}

// Get the localized URL for that node.
$localized_url = $test_node->toUrl('canonical', [
  'language' => $test_node->language(),
])->toString();
1
  • 1
    Once you have the translated node object you can call "toUrl" without the language option. Commented Jan 11, 2022 at 14:22
1

As per the new change record in Drupal 8.8.0 path.alias_manager is deprecated and path_alias.manager is introduced.

New syntax is as follows :

$url_alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'. $nid, $langcode);
-8

I was hoping for a more "Drupalesque" solution, but here's what I made myself to do the job:

  function getPathFromNID($nid) {
    $db = \Drupal::database();

    $data = $db
        ->select('url_alias', 'u')
        ->fields('u', ['alias'])
        ->condition('source', '/node/' . $nid)
        ->execute()
        ->fetchField();
    return $data;
  }
2
  • 5
    No, you should never be directly querying core tables like this in Drupal 8. Use the API like all the above answers.
    – anonymous
    Commented Jul 8, 2020 at 17:32
  • One of the issues with this is if there's a core update that changes how these aliases are stored this code will break.
    – Amy
    Commented Jun 17, 2021 at 19:02

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.