Creating a link from node ID in Drupal 8
Asked Answered
X

9

28

I am checking out Drupal 8 and try to generate a link based on the node ID of an article. In Drupal 7 it is something like:

$options = array('absolute' => TRUE);
$nid = 1; // Node ID
$url = url('node/' . $nid, $options);

This results into an absolute link with the correct url-alias.

So the url()-function seems to be deprecated; what is the Drupal-8 way? Looks like a really basic function for me but I could not find any useful references.

Xanthous answered 14/2, 2016 at 19:20 Comment(0)
H
51

You need to use the \Drupal\Core\Url class, specifically its fromRoute static method. Drupal 8 uses routes which have name different from their actual URL path. In your case, the route to use is the canonical route for a node entity: entity.node.canonical. \Drupal\Core\Url::fromRoute() will not return a string, but an object. To get the URL as a string, you need to call its toString() method.

$options = ['absolute' => TRUE];
$url = \Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => 1], $options);
$url = $url->toString();

The static method is not easily testable, $url->toString() require an initialized container. Your can replace the static method with a call to UrlGeneratorInterface::generateFromRoute() on the url_generator service.

$options = ['absolute' => TRUE];
$url = $this->url_generator->generateFromRoute('entity.node.canonical', ['node' => 1], $options);
$url = $url->toString();

Unfortunately, this method is marked as @internal so you are not supposed to use it in user code (ie. outside Drupal core).

Hydroscope answered 14/2, 2016 at 23:34 Comment(3)
this did it for me. thanks for the snippet! if an alias is defined i get the alias, if not I get the link with .../node/id.Xanthous
Could you explain how to use it ? Where did I change / add code ? In theme > preprocess ? Url.php or the Core ? It is difficult to find global answer when we start Drupal..Warms
@PaulLeclerc You should never change something in the core just as a general note. You can use the code examples above wherever you need it. It works in every file where you can use php. We obviously can not answer this for you because we do not know what you want to do.Xanthous
I
8

Create absolute URL:

$options = ['absolute' => TRUE];
$url_object = Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => $nid], $options);
// will output http://example.com/path-to-my-node

Create absolute link object:

$options = ['absolute' => TRUE, 'attributes' => ['class' => 'this-class']];
$node_title = Drupal\Core\Render\Markup::create('<span>' . $node_title . '</span>');
$link_object = Drupal\Core\Link::createFromRoute($node_title, 'entity.node.canonical', ['node' => $nid], $options);
// will output <a href="http://example.com/path-to-my-node" class="this-class"><span>My Node's Title</span></a>
Incipient answered 19/10, 2016 at 17:30 Comment(0)
C
6

In case you have fully loaded node object you can simply call $node->toUrl() to get required URL. By default it returns canonical URL for a node (node/NID) but it is possible to build other URLs listed in Node entity definition (see Drupal\node\Entity\Node.php). Same is true for other entity types.

$options = ['absolute' => TRUE];
$view_link = Link::fromTextAndUrl(t('View'), $node->toUrl('canonical', $options));
$edit_link = Link::fromTextAndUrl(t('Edit'), $node->toUrl('edit-form', $options));
$delete_link = Link::fromTextAndUrl(t('Delete'), $node->toUrl('delete-form', $options));
Clobber answered 10/9, 2017 at 6:39 Comment(0)
M
2

hehe, this is the shit in terms of getting URL from field (Twig version of getting that URL)

If you want the URL (and title) that is in a field you have to get to object of class: Drupal\Core\Url

If you got the node by drupal_entity (Twig Tweaks) then you have: (I'll use "tab" as that node) tab['#node'].field_link

This gives you by using:

tab['#node'].field_link.uri -> the URI (URI is not URL)

tab['#node'].field_link.title -> the title

but, that's not the end.

it's better to acess Drupal\link\Plugin\Field\FieldType\LinkItem by:

tab['#node'].field_link.get(0)

tab['#node'].field_link[0]

(both do the same)

then you can access what's most interesting:

tab['#node'].field_tab_link[0].getUrl() a Drupal\Core\Url object.

You can access this object also by using this line below, from within that's node template file: content.field_link[0]['#url'] (this is also Drupal\Core\Url object)

That object has methods:

  • isExternal() -> is link to outside (ie. http://cnn.com)
  • isRouted() -> is link to inside of your site
  • getRouteName() -> name of the route
  • getRouteParameters() -> which gives you an array of values, here(we get ID of that node) you would have ['node' => ID]

You should use it like that:

{% set tabURL = tab['#node'].field_link[0].getUrl() %}

{% if tabURL.isExternal() %}
    {% set link_path = tab['#node'].field_tab_link.uri %}

{% elseif tabURL.isRouted() %}
    {% set link_path = path(tabURL.getRouteName(), tabURL.getRouteParameters()) %} {# /node/12 #}

{% endif %}
Mehalick answered 23/5, 2017 at 10:13 Comment(0)
C
2

Here is my answer for node edit link.

$nodeInfo = $entity->get('nid')->getValue();
$nodeId = $nodeInfo[0]['value'];
$options = ['absolute' => TRUE];
$url = \Drupal\Core\Url::fromRoute('entity.node.edit_form', ['node' => $nodeId], $options);
$url = $url->toString();
Chilson answered 17/12, 2018 at 13:10 Comment(0)
D
2

I find it easier to work with the $node object. Then let my IDE show me all the available methods of the object. So the simplest is

$link = $node->toLink();

This gets you a link to the full-page node, with the node title as the link text.

If you want to change the title/route, you could do something like

$link = $node->toLink('Edit this node', 'edit-form');
Dissent answered 27/5, 2021 at 2:16 Comment(0)
G
2

Full absolute path with correct language prefix:

$url_options = [
  'absolute' => TRUE,
  'language' => \Drupal::languageManager()->getCurrentLanguage(),
];
$Path = Url::fromRoute('entity.node.canonical', ['node' => 81], $url_options)->toString();
// prints https://example.com/fr/mon-page
Gonna answered 25/8, 2021 at 12:57 Comment(0)
S
0

I'm ready to be downvoted here. Apologize, I haven't completely accept this yet.

In Drupal 7 took (only) 28 chars I can still remember and type well.

l($node->title, $node->nid);

I guess something like this may improve the life quality of a D8 coder.

      function d8l ($text, $nid, $some_options)  {
         $options = [
           'query' => ['foo' => 'bar'],
           'fragment' => 'anchor-div',
           'attributes' => ['class' => ['my-class'], 'rel' =>'nofollow'],
         ];
         $link = Link::fromTextAndUrl(t($text), 
         Url::fromUri('internal:/node/' . $nid, $options))->toString();
         return $link;
       }   
Scapegoat answered 22/9, 2020 at 11:55 Comment(0)
C
0

Some good answers here and lot of useful info. For edit links, if you have the node, I was able to do like this $options = [ 'absolute' => TRUE, 'language' => \Drupal::languageManager()->getCurrentLanguage(), ];

and editurl = $edit_node->toUrl('edit-form', $options)->toString();

more info in drupal/web/core/lib/Drupal/Core/Entity/EntityInterface.php

Clarino answered 2/3, 2022 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.