0

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."

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.

  • 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? – usernameabc Dec 18 '17 at 23:47
  • 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 – usernameabc Dec 19 '17 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/… – 4k4 Dec 19 '17 at 16:37
  • Rather than running the risk of #node not displaying, I will do this through the preprocess (see answer below) – usernameabc Dec 20 '17 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 #}
  • This code is outdated since a year, the eck templates are using the D8 standard pattern now. – 4k4 Dec 30 '17 at 10:40

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.