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()]);