41

I have a Link field named field_my_link (machine name).

Within a Twig template I can get the link's URL value with this:

{{ node.field_my_link.uri }}

If inside the Link's URL there is an external URL, e.g. http://example.com it works good.

But, if inside the Link's URL there is stored an internal URL, e.g. "/node/11", I get a value like this:

"internal:/node/11"

with the "internal:" prefix.

How can I get the valid URL?

For example, if the link's URL is "http://example.com" I want "http://example.com" (this already works), if the link's URL is "/node/11" I want the relative URL "/node/11", if the link's URL is "<front>" I want the URL "/", etc.


EDIT

I can get the value I want within a PHP preprocess function, using this:

$url = $variables['node']->get('field_my_link')->first()->getUrl();

How can I access the same value within the Twig template?

I know I can do this within the preprocess function:

$variables['my_url'] = $url;

Then access the url within Twig using {{ my_url }}, but I would avoid to write a preprocess function each time I have a link field.

53

Your PHP from your latest edit would translate into twig like this:

{{ node.field_my_link.0.url }}

This works like this, 0 returns the first item of the field item list, url gets the url object and because twig will cast this object as a string this will call the magic method toString() and will output the url as a string value.

You only need to use url, because twig looks automatically for the method getxyz() if there is no property with that name xyz.

| improve this answer | |
  • Thank you. Now I make a test with this function. Do you know if can I use this function also on links' URIs? What happen if node.field_my_link.uri is an external url like http://www.example.com? – Andrea Apr 26 '16 at 12:25
  • 1
    I tried with file_url(node.field_my_link.uri), and if node.field_my_link.uri is "http://www.example.com" it works (it leaves the url unchanged), but if node.field_my_link.uri is "internal:/" the function returns "/internal%3A/" (instead of "/").. – Andrea Apr 26 '16 at 12:32
  • I just saw your edit.. Sadly it doesn't works, the code node.field_my_link.entity.uri.value returns a null value.. Any other ideas? – Andrea Apr 30 '16 at 7:32
  • 1
    Yeah, it works. The syntax is a bit scary, but it does its job. – Andrea Apr 30 '16 at 11:53
  • 1
    This shouldn't be marked as "solution" as the file_url() function works just with files and not with link fields. The thread starter asked for the raw url output of a "link field". – mogio Dec 6 '16 at 13:30
23

You can access the render array element directly, in your case:

{{ node.field_my_link[0]['#url'] }}
| improve this answer | |
  • This one worked for my. – esQmo_ Oct 23 '18 at 21:05
  • It appears this is now the correct answer. – maskedjellybean Mar 31 at 21:40
17

You have to cover both cases: external and internal URLs.

First let's check if the URL is external and simply print its *.uri.

Else if it's internal we have to wire its route name and parameters through Drupal's path($name, $parameters, $options) function.

{% if node.field_link.0.url.external %}
  <a href="{{ node.field_link.uri }}">
    {{ node.field_link.title }}
  </a>
{% else %}
  <a href="{{ path(node.field_link.0.url.routeName, node.field_link.0.url.routeParameters) }}">
    {{ node.field_link.title }}
  </a>
{% endif %}
| improve this answer | |
  • 2
    Thank you, this is exactly what I needed: get the url from a link field as a string: {% set url = path(node.field_link.0.url.routeName, node.field_link.0.url.routeParameters) %} Then I can create a custom link:` <a href="{{ url }}" class="mycustomclass">custom link text</a> No preprocess needed and no need to go via content.field_link, so no need to do anything in the 'Manage display' for the link field just to get the url. – user33560 Mar 1 '18 at 8:56
10

I had to do this on a Link Field in a Block. This worked well:

{{ content.field_my_link[0]['#url']|render }}
| improve this answer | |
  • 4
    It is also fine to use {{ content.field_my_link[0]['#url'] }} without render, as in twig template, render array are automatically rendered when printed. – eric.chenchao Jun 6 '17 at 2:35
8

I know it's an old post but with the last version of Drupal 8 (8.6) you can directly display the url for both version (external and internal):

node.field_link.0.url

And if you need to know if the link is external or not (for my case it was for the target), you can use that:

node.field_link.0.url.external

Example:

<a href="{{ node.field_link.0.url }}" title="Title" target="{{ node.field_link.0.url.external ? '_blank' : '_self' }}"
| improve this answer | |
  • 1
    I like your usage of target = _self for internal and external _blank. It improves the UX. – Tyeth Apr 27 at 11:19
6

you can also use something like the following, it all depends of the type of object you are extracting and the field name, In my case it was a paragraph with a field named field_link and the following worked:

{{ paragraph.field_link.get(0).getUrl().toString() }}
| improve this answer | |
  • You are the man today my friend! Look at this craziness! I added a page_link field on one of my taxonomies. So i have to do this: {% set page_url = content.field_category.0['#options'].entity.field_page_link.get(0).getURL().toString() %} Now it outputs the url instead of the node ID, thank you! – Robbiegod Dec 13 '19 at 22:52
  • It worked for me to, this is the solution! – Yann Chabot Mar 30 at 15:35
  • 1
    You saved me again today! This time a paragraph field and getting the full internal link url. {% set full_link_url = content.field_content_block.0['#paragraph'].field_external_link.get(0).getUrl().toString() %} - BTW, this worked in a node template. – Robbiegod Apr 9 at 15:43
2

In paragraph, to get the link url and link name -

<a href="{{ content.FIELD_LINK_NAME[0]['#url']|render }}">
   {{ content.FIELD_LINK_NAME[0]['#title']|render }}
</a>
| improve this answer | |
1

I know it's horrible, but if nothing else works:

{{ link|replace({'internal:':''}) }}

My situation: accessing a Link field via an overridden views template: views-view-fields.html.twig

I had to get the variable from:

row._entity.field_machine_name.value.0.uri

(I gave up trying to use the fields variable, you can seemingly get a .content property out of that, but not much else)

….field_machine_name.value is just a flat array, which only has a uri key, NOT url, and the filters mentioned in other answers (toString(), render etc.) simply don't seem to work here.

| improve this answer | |
0

Here's another way to do this. This example exclude the use of the Title field.

{% set link_url = content.field_link.0['#url'] %}
{% set link = link_url ? link_url : content.field_link.0['#title'] %}

{% if link %}
  {{ link.toString() }}
{% endif %}

Possible results

# Input ---------------- Output -----------
# This is a node (23)    /relative/url
# <front>                /
# https://drupal.org     https://drupal.org
| improve this answer | |

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.