Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

In order to support a consistent and comprehensible API for module developers to create links using the Drupal 8.0.x routing API, code that was forward-ported from Drupal 7 has been retired, the use of route name and parameters required in almost all cases and "system path" is not supported except as a temporary value entered into forms by end users that is converted during save.

This change introduces 2 new static factory methods on the \Drupal\Core\Url class:

Url::fromRoute($route_name, $route_parameters, $options)
Url::fromUri($uri, $options)

See api page Url::fromUri() for documentation of arguments.

This change also changes \Drupal\Core\Utility\LinkGenerator so that there is a single generate() method that accepts a Url value object, instead of having multiple methods to generate a link.

The renamed _url() and _l() are deprecated and *will* be removed before 8.0.0 is released.

Drupal 7:

// Internal path.
$internal_link = l(t('Book admin'), 'admin/structure/book');

// External Uri.
$external_link = l(t('External link'), 'http://www.example.com/', array('external' => TRUE));

Drupal 8:

// Internal path (defined by a route in Drupal 8).
use Drupal\Core\Url;
$url = Url::fromRoute('book.admin');
$internal_link = \Drupal::l(t('Book admin'), $url);

// External Uri.
use Drupal\Core\Url;
$url = Url::fromUri('http://www.example.com/');
$external_link = \Drupal::l(t('External link'), $url);
Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

Mile23’s picture

Note that in an ideal world, all relevant base classes will contain their own reference to the link generator, so you should be able to say $this->l() rather than \Drupal::l()

For instance, Drupal\Core\Controller\ControllerBase and Drupal\Core\Entity\EntityForm allow this.

If you are implementing your own form class or content controller, learn how to do dependency injection and remove your dependency on \Drupal. Unit testers everywhere will thank you.

wizonesolutions’s picture

Why do the code samples here use t() and not $this->t()(? Is it shorthand, or is it procedural code?

FillPDF Service - http://fillpdf-service.com - Hosted solution for FillPDF

ngocketit’s picture

If you're writing procedural code in .module file for example, you can use t() and \Drupal::l() functions directly but if you're in a class that uses LinkGeneratorTrait or StringTranslationTrait, you should use $this->l() or this->t().

subhojit777’s picture

The API has been changed but how can we specify other link attributes like query, fragment, class, etc.

Regards,
Subhojit Paul

xjm’s picture

Works the same way as in D7 and earlier.

Amber Himes Matz’s picture

Based on my experience implementing the examples in this change record I wrote up an article here:

A Peek at Traits in Drupal
https://drupalize.me/blog/201503/dependency-injection-traits-drupal-8

krknth’s picture

I don't know the right way of converting relative to absolute using l()
But these is working

$relative_url = Url::fromUserInput('/my-custom-page');
$link = \Drupal::l('My custom page', $relative_url);
Huelfe’s picture

If you want to create a absolute URL with no link you can use this:

$url = \Drupal\Core\Url::fromUserInput('/mypath', array('absolute' => TRUE))->toString();

sime’s picture

The D8 example here uses \Drupal::l which is now deprecated. I think this is the right way now...

use Drupal\Core\Link;
use Drupal\Core\Url;

...

$link = Link::fromTextAndUrl('some text', Url::fromUri('http://google.com'));
$html = $link->toString();
alexrayu’s picture

Can link attributes be specified? A class?

screon’s picture

Details on how to do this can be found here: http://drupal.stackexchange.com/a/187768/59648.

petiar’s picture

It looks like the more lines of code the better. What's wrong with l()???

--
Petiar
http://petiar.sk

emarchak’s picture

Is this defined in a service somewhere, or do I have to use the global namespace?

use Drupal\Core\Url;
$url = Url::fromUri('http://www.example.com/');
di3gopa’s picture

For reference, Drupal::l is deprecated now, you should use the Link class now:

$link = Link::fromTextAndUrl($text, $url)

https://api.drupal.org/api/drupal/core!lib!Drupal.php/function/Drupal%3A...

septesian’s picture

Under 7 the l() function allowed you to specify an image or text for the link the current version doesn't allow this. The Link class doesn't seem to have the relevant functionality either so how do you do it. Under 7 I have a list of items with an image which can be selected to display the details of the item. At the moment I cant see a way to convert this code to 8 other than replacing the image with text.

birdsnbees’s picture

I would like to share this page Drupal 8 Link creation with query, fragment and attributes examples - https://www.webfoobar.com/node/67

mark_fullmer’s picture

The above is a very nice, comprehensive example of more complex links in D8.