23
votes

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.

9

9 Answers

41
votes

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).

6
votes

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>
5
votes

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));
2
votes

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 %}
2
votes

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();
0
votes

You need to use Drupal\Core\Url; class.

$url= Url::fromRoute('root', $route_parameters=array());

$link = \Drupal::l(t('label'), $url);  

Example:

If you pass argument

$url = Url::fromRoute('test.page', $route_parameters = array('test' => 1));

Otherwise

$url = Url::fromRoute('test.page');
$link = \Drupal::l(t('Label'), $url);
0
votes

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;
       }   
0
votes

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');
0
votes

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