1

We have an ECK Bundle that has an Entity Reference to Article and Basic Page content type. In the twig template we are using the following line below to get the node's nid value and then using that in the twig template to create a link to that node. However, we are getting the following error message while logged out (for logged in users it works fine).

How can we get the node's url for both anonymous and logged in users?

Twig template (eck-entity--component--eck-ref-node--default.html.twig where eck-ref-node is the eck bundle name):

{% set field = entity.field_eck_ref %}
{% set ref_node = field.0['#node'] %}
{% set nodeId = ref_node.nid.value %}
{% set nodeURL = path('entity.node.canonical', {'node': nodeId}) %}

<a href={{ nodeUrl }}>
...
</a>

Error:

Uncaught PHP Exception Symfony\Component\Routing\Exception\InvalidParameterException: "Parameter "node" for route "entity.node.canonical" must match "\d+" ("" given) to generate a corresponding URL."

2 Answers 2

0

#node is usually part of a render array. Don't know why you named this entity. If it were a real entity object, then you could get the node id directly with .target_id instead of ['#node'].

The problem with keys in render arrays like #node is, they are only included if needed for rendering, so it's not a good idea to write code which fails if it does not exist.

You have to look for the entity object. According to the template doc the entity is named eck_entity:

{#
/**
 * @file
 * Default theme implementation to display an ECK entity.
 *
 * Available variables:
 * - eck_entity: The full ECK entity with limited access to object properties
 *   and methods. Only "getter" methods (method names starting with "get",
 *   "has", or "is") and a few common methods such as "id" and "label" are
 *   available. Calling other methods (such as node.delete) will result in an
 *   exception.
 * - content: All ECK entity items. Use {{ content }} to print them all,
 *   or print a subset such as {{ content.field_example }}. Use
 *   {{ content|without('field_example') }} to temporarily suppress the printing
 *   of a given child element.
 * - attributes: HTML attributes for the containing element.
 *
 * @see template_preprocess_eck_entity()
 *
 * @ingroup themeable
 */
#}

If this is the template you use, then try something like this to access the field object and the target id of the node:

{% set field = eck_entity.field_eck_ref %}
{% set nodeId = field.0.target_id %}

This works independently of user permissions.

And only build the url when you are sure you have a node id, because otherwise your code still fails if the field is empty.

5
  • the reason i have entity is because when i used twig debug, it was teling me to use eck-entity.html.twig which only came with <div {{attributes}}> {{entity}} </div> What is the name of the twig that you just added? Commented Dec 18, 2017 at 23:47
  • cgit.drupalcode.org/eck/tree/templates/…
    – 4uk4
    Commented Dec 18, 2017 at 23:49
  • it appears I have another version of ECK because i don't see that in my eck-entity.html.twig file. however, seeing template_preprocess_eck_entity, i was able to get the answer by using that hook to get the url. I was not able to get the target_id, but using preprocess helped. I shall post answer Commented Dec 19, 2017 at 1:29
  • You can do this both in PHP or Twig the same way. This is a question in which language you feel comfortable. But I wouldn't base my code on a template structure which is outdated since a year now, see the commit cgit.drupalcode.org/eck/commit/…
    – 4uk4
    Commented Dec 19, 2017 at 16:37
  • Rather than running the risk of #node not displaying, I will do this through the preprocess (see answer below) Commented Dec 20, 2017 at 0:58
0

I ended up using template_preprocess_eck_entity() with the following lines of code to get the node URL and passed it into the Twig template. I ended up calling Entity::url to get the canonical URL.

template_preprocess_eck_entity(&$vars) {
$eck = $vars['entity']['#component'];
if($eck->bundle() == 'eck_bundle_name') {
    if($eck->hasField('field_eck_bundle')) {
         $ref = $eck->get('fiedl_eck_bundle'));
         $entRef = $ref->offsetGet(0)->get('entity');
         $node = $entRef->getTarget()->getValue();
         $node_url = $node->url();
         $vars['field_eck_bundle']['node_url'] = $node_url;
    }
}

}//end template_preprocess_eck_entity()

eck-entity--component--eck-ref-node--default.html.twig

{{ field_eck_bundle.node_url }} {# this works #}
1
  • This code is outdated since a year, the eck templates are using the D8 standard pattern now.
    – 4uk4
    Commented Dec 30, 2017 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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