We have a Basic Page content type with a link field (field_link). When we call the mymodule_preprocess_node(&$variables) hook in a custom module we use ksm($node->get('field_link')->first()) and it returns a Drupal\link\Plugin\Field\FieldType\LinkItem. We need to extract the URL from this fields and have found two ways to do it (see below). What is the correct way to get the URL from the field?

The reason for extracting the URL is that we need to wrap a set of custom fields with the link so we can have a HTML structure similar to below.

HTML structure:

<a href="/some/path" target="_blank">
  <img src="some/image/path">
  <span> Some title field </span>


function mymodule_preprocess_node(&$variables) {
  $node = $variables['node'];
  $node_field_link = $node->get('field_link')->first();

  // Do we use this?
  $node_field_link_url = $node_field_link->getUrl()->getUri();

  // Or do we use?
  $node_field_link_url = $node_field_link->get('uri')->getValue();

Get the Url object from the link field with LinkItemInterface::getUrl and build a new link, for example:

$variables['link_with_image'] => [
  '#type' => 'link',
  '#title' => [
    '#theme' => 'image',
    '#uri' => $image_uri,
    '#width' => 60,
    '#height' => 40,
    '#alt' => $image_alt,
  '#url' => $node->field_link->first()->getUrl();
  '#attributes' => ['target' => '_blank'],

Normally you don't do this in preprocess and build such render arrays in a field formatter, see for example Image Link Attributes and Linked Field.

| improve this answer | |

I find the best way to get a url especially when I'm using it in cases where I need to wrap custom html around it is to get the url object and then use the toString Method.

$node_field_link_url = $node_field_link->getUrl()->toString();

The getUrl() method of the LinkItem object returns a Url object. See https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Url.php/class/Url/8.2.x And Url objects have a toString method that returns the string representation of that url.

| improve this answer | |
  • There was some discussion to avoid using toString() and instead using toRenderArray(). Just a suggestion. – Postovan Dumitru Aug 14 '18 at 7:00
  • Do you have a link to a discussion about that? I'm curious as to why. – Matt Aug 14 '18 at 17:31
  • 1
    Sorry, @matt! My bad, mistook the documentation for the Link::toString(). – Postovan Dumitru Aug 15 '18 at 8:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.