Working with links
One of the principal characteristics of a web application is the myriad of links between its resources. They are in fact the glue that brings the internet together. So, in this section, I want to show you a few common techniques used while working with links programmatically.
There are two main aspects when talking about link building in Drupal—the URL and the actual link tag itself. So, creating a link involves a two-step process, but can also be shortened into a single call via some helper methods.
The URL
URLs in Drupal are represented with the Drupal\Core\Url
class, which has a number of static methods that allow you to create an instance of it. The most important of these is ::fromRoute()
, which takes a route name, route parameters (if any are needed for that route), and an array of options to create a new instance of Url
. There are other such methods available that turn all sorts of other things into a Url
, most notably the ::fromUri()
method, which takes an internal or external URI. These methods can be very helpful, especially when dealing with dynamically obtained data. However, when hardcoding, it›s always best to work with route names because that allows you to later change the actual path behind that route without affecting your code.
There are many options that can be passed to Url
when instantiating it inside the $options
array. You can pass an array of query parameters, a fragment, and others. These will then help construct a URL as complex as you need without having to deal with strings yourself. I suggest that you check out the documentation above the ::fromUri()
method because it describes them all. Also, keep in mind that the options are pretty much the same, regardless of the method that you use to create the Url
object.
The link
Now that we have a Url
object, we can use it to generate a link. We can do this in two ways:
- Use the
LinkGenerator
service (namedlink_generator
) and call itsgenerate()
method by passing the link text and theUrl
object we have obtained. This will return aGeneratedLink
object, which contains the actual string representation of the link as well as some cache metadata. - Use the
\Drupal\Core\Link
class, which wraps a render element (we will talk more about render elements in Chapter 4, Theming) to represent the link.
Let's take a look at an example of both, from start to finish.
Consider this example of generating a link using the service:
$url = Url::fromRoute('my_route', ['param_name' => $param_value]); $link = \Drupal::service('link_generator')->generate('My link', $url);
We can then directly print $link
because it implements the __toString()
method.
Now, consider this example of generating a link using the Link
class:
$url = Url::fromRoute('my_other_route'); $link = Link::fromTextAndUrl('My link', $url);
We now have $link
as a Link
object whose toRenderable()
method returns a render array of #type => 'link'
. Behind the scenes, at render time, it will also use the link generator to transform that into a link string.
If we have a Link
object, we can also use the link generator ourselves to generate a link based on its own data:
$link = \Drupal::service('link_generator')->generateFromLink($linkObject);
Which way to link?
As we saw, we have a number of ways to create links and URL representations, but when it comes to creating a link, which method should we use? There are advantages and disadvantages to each one.
When it comes to the URL, as mentioned, it's a good idea to stick to hardcoding routes rather than URIs. However, if you are working with dynamic data, such as user input or stored strings, the other methods are perfectly valid. I recommend that you look at the Url
class in detail because you will be using it quite a bit as you develop Drupal modules.
Regarding the actual links, using the service to generate a link means that you are creating a string at that point in the code. This means that it cannot be altered later in the process. Instead, using the Link
class falls nicely in line with the entire render array rationale of delaying the actual generation to the last possible moment. We will talk more about render arrays later on. Generating links early on could also have consequences with the render system and cache bubbling, so it's always better to stick with the Link
objects or render arrays with #type => 'link'
.
When it comes to entities, you can and should use the helper methods on the base entity classes to generate links and URLs to these entities. We will talk more about entities later in this book.