Skip to main content
Category:

In this tuto, I will show you plenty of ways how to create links when using Drupal 8.

The easiest way to create internal links is using Link::createFromRoute

Example:

<?php
namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Link;


class MyModuleController extends ControllerBase {

  /**
   * @return string[]
   */
  public function index() {

    return [
      '#markup' => Link::createFromRoute('Link Title', 'entity.node.canonical', ['node' => 1])->toString(),
    ];
  }

}

 

Using the Url object gives you more flexibility to create links, for instance, we can do the same as Link::createFromRoute method using the Url object like this:

<?php
namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Link;
use Drupal\Core\Url;


class MyModuleController extends ControllerBase {

  /**
   * @return string[]
   */
  public function index() {

    return [
      '#markup' => Link::fromTextAndUrl('Link Title', Url::fromRoute('entity.node.canonical', ['node' => 1]))->toString(),
    ];
  }

}

And actually Link::fromTextAndUrl is what Drupal recommends instead of using the deprecated l() method. Passing the Url object to the link object gives you great flexibility to create links, here are some examples:

Internal links which have no routes:

$link = Link::fromTextAndUrl('This is a link', Url::fromUri('base:robots.txt'));

External links:

$link = Link::fromTextAndUrl('This is a link', Url::fromUri('http://www.codimth.com'));

links with only the fragment (without url) :

$link = Link::fromTextAndUrl('This is a link', Url::fromUri('internal:#fragment'));

Using the data provided by a user:

$link = Link::fromTextAndUrl('This is a link', Url::fromUserInput('/node/1');

The param passed to fromUserInput must start with /,#,? or it will throw an exception.

Linking entities:

$link = Link::fromTextAndUrl('This is a link', Url::fromUri('entity:node/1'));

Entities are a special case, and there are more ways to link them:

$node = Node::load(1);
$link = $node->toLink();
$link->setText('This is a link');

And even using the route:

$link = Link::fromTextAndUrl('This is a link', Url::fromRoute('entity.node.canonical', ['node' => 1]));

Drupal usually expects a render array if you are going to print the link, so the Link object has a method for that:

$link->toRenderable();

which will return an array.

Final tips:

Searching a route using Drupal Console

The easiest way to find the route of a specific path is using Drupal Console, with the following command.

drupal router:debug | grep -i "\/node"

That will return something like:

entity.node.canonical                                 /node/{node}
 entity.node.delete_form                               /node/{node}/delete
 entity.node.edit_form                                 /node/{node}/edit
 entity.node.preview                                   /node/preview/{node_preview}/{view_mode_id}
 entity.node.revision                                  /node/{node}/revisions/{node_revision}/view
 entity.node.version_history                           /node/{node}/revisions
 node.add                                              /node/add/{node_type}
 node.add_page                                         /node/add
 node.multiple_delete_confirm                          /admin/content/node/delete
 node.revision_delete_confirm                          /node/{node}/revisions/{node_revision}/delete
 node.revision_revert_confirm                          /node/{node}/revisions/{node_revision}/revert
 node.revision_revert_translation_confirm              /node/{node}/revisions/{node_revision}/revert/{langcode}
 search.help_node_search                               /search/node/help
 search.view_node_search                               /search/node
 view.frontpage.page_1                                 /node

Listing all the possible routes with that word, we can choose one and do:

drupal router:debug entity.node.canonical

And that will display more information about a specific route:

Route             entity.node.canonical
 Path              /node/{node}
 Defaults
  _controller      \Drupal\node\Controller\NodeViewController::view
  _title_callback  \Drupal\node\Controller\NodeViewController::title
 Requirements
  node             \d+
  _entity_access   node.view
  _method          GET|POST
 Options
  compiler_class   \Drupal\Core\Routing\RouteCompiler
  parameters       node:
                     type: 'entity:node'
                     converter: paramconverter.entity

  _route_filters   method_filter
                   content_type_header_matcher

  _route_enhancers route_enhancer.param_conversion

  _access_checks   access_check.entity

So in this way we can search the route without the needing to search in all the *.routing.yml files and in this example the route is entity.node.canonical and the param expected is node.

Print links directly within a twig template

It is also possible to print links directly on the twig template with the following syntax:

<a href="{{url('entity.node.canonical', {'node': node.id( ) }}"> {{ 'This is a link'|t }} </a>

Add links inside a t() method.

If you want to add a link inside the t() you can do like this:

use Drupal\Core\Url;
$url = Url::fromRoute('entity.node.canonical', ['node' => 1]);
$this->t('You can click this <a href=="@link">Link</a>', ['@link' => $url->toString()]);

Riadh Rahmi

Senior Web Developer PHP/Drupal & Laravel

I am a senior web developer, I have experience in planning and developing large scale dynamic web solutions especially in Drupal & Laravel.

Web Posts

Search

Page Facebook