// From a route.
$url = Url::fromRoute('contact.site_page');
// From a URI.
$url = Url::fromUri('http://example.com');
// Link to an internal path defined by a route.
$link = Link::createFromRoute('This is a link', 'entity.node.canonical', ['node' => 42])
// Link to an external URI.
$link = Link::fromTextAndUrl('This is a link', Url::fromUri('http://example.com'));
// Get output as a render array. Preferred.
$link->toRenderable();
// Get output as a string.
$link->toString();
URLs in Drupal are represented as value objects and can be generated using the \Drupal\Core\Url
class. This should be used whenever you need a URL in a non-HTML context. For example, help text where you actually want to display the URL and not have it be linked. Or when determining the path for a redirect.
Rule of thumb: If you just want the URL, use the Url
class.
Links are HTML markup, albeit very small chunks, and should therefore be represented as render arrays any time they are going to be displayed in the context of HTML. The \Drupal\Core\Link
class provides helpers for quickly creating link content.
Rule of thumb: If you want to display a link that someone can follow by clicking on it, use the Link
class.
The \Drupal\Core\Url
class has a bunch of factory methods for generating URL objects. Once you've got a URL object you can convert it to a string or use it to create a link.
For URIs that are external to Drupal, don't have a corresponding route (e.g. robots.txt), are based on user input and point at something internal, or represent a Drupal entity you can use \Drupal\Core\Url::fromUri()
.
$url = Url::fromUri('https://drupal.org/about');
The rest of these examples work by adding 1 of 3 different schemes as a prefix to the URI pattern.
$url = Url::fromUri('base:/robots.txt');
$url = Url::fromUri('internal:/about/contact');
This exists as a shortcut for creating URLs to entities by following a known pattern.
// Pattern is "entity:/{entity\_type}/{entity\_id}"
$url = Url::fromUri('entity:/node/42');
For URIs that represent an internal Drupal route, which is pretty much everything you might link to within your application itself, you should use \Drupal\Core\Url::fromRoute()
.
// From route with no parameters.
$url = Url::fromRoute('contact.site_page');
// From route with additional parameters.
$url = Url::fromRoute('entity.node.canonical', ['node' => 42]);
Both of the above factory methods take an optional $options
argument which can be used to add query string parameters or URL fragments to a URL.
$options = ['fragment' => 'feedback'];
$url = Url::fromRoute('entity.node.canonical', ['node' => 42], $options);
Result:
/node/42#feedback
$options = ['query' => ['name' => 'joe', 'hats' => 'no']];
$url = Url::fromRoute('entity.node.canonical', ['node' => 42], $options);
Result:
/node/42?name=joe&hats=no
As mentioned above, links are HTML and should therefore be output as render arrays. There is a '#type' => 'link'
render element you can use.
Using a #link
element in a render array. See \Drupal\Core\Render\Element\Link
.
Here's an example of what this looks like as a render array:
$build['link'] = [
'#type' => 'link',
'#title' => $this->t('A link to example.com'),
'#url' => Url::fromUri('https://example.com'),
];
You can and should use the factory methods of the \Drupal\Core\Link
class to create a link object, then use the Link::toRenderable()
method to help with this.
Create a link to an internal route without having to first generate a URL object:
$link = Link::createFromRoute('Text of the link', 'entity.node.canonical', ['node' => 42]);
Or, create a link from a string of text and any URL object:
$url = Url::fromUri('https://drupal.org/about');
$link = Link::fromTextAndUrl('Text to display', $url);
Once you've got a Link
object you can convert it to a render array. This is the preferred method for displaying links.
$build['link'] = $link->toRenderable();
// Optionally add attributes to the link element.
$build['link']['#attributes'] = ['class' => ['my-link'], 'data-id' => $id];
Or you can output it as a string.
$output = $link->toString();
Entity objects all have an $entity->toUrl()
and $entity->toLink()
methods. So if you're already working with an entity object this is a quick way to get a URL or Link object pointing to the entity without having to figure out the appropriate route and parameters.
You can also print links within a Twig template.
<a href="{{ url('entity.node.canonical', {'node': node.id}) }}">{{ 'This is a link'|t }}</a>
Twig code example
For more details on the handling links in Twig templates see Routes, URLs, and Links in Twig Templates.
Adding links inside a t()
method requires using a placeholder and passing the link in a string.
use Drupal\Core\Link;
use Drupal\Core\Url;
$link = Link::fromTextAndUrl('This is a link', Url::fromRoute('entity.node.canonical', ['node' => 1]));
$this->t('You can click this %link' ['%link' => $link->toString()]);
You might be wondering if there is a service you should use with your controller for these utilities. Links and URLs are generally considered value objects and therefore don't need to be injected. You can, and should, just use the classes directly.
use \Drupal\Core\Url;
use \Drupal\Core\Link;
There are a whole lot of deprecated methods for creating links which still work, but you shouldn't use them. This is a result of the long, and winding, path from the Drupal 7 link generation code to the Drupal 8 code and trying to maintain compatibility during the transition. The information above represents the currently recommended way of creating links and ensures that the code you write will be compatible going forward.