2

I am using Drupal 8. I would like to check if user (anonymous or logged user) is node author in node.html.twig, like below:

{# node.html.twig #}
  {% if is_author %}
    You are node author
  {% else %}
    You are not node author
  {% endif %}

Below codes not work:

/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHENE_preprocess_node(&$variables) {
  $global $user;
  if ($variables['node']->uid == $user->uid) {
    $variables['is_author'] = TRUE;
  }
  else {
    $variables['is_author'] = FALSE;
  }
}

How could I create variable 'is_author' in node.html.twig?

1
  • 2
    Don’t use global $user. Use the current user service. Also all function names must be underscore only.
    – Kevin
    Dec 24, 2018 at 4:39

2 Answers 2

1
/**
 * Implements hook_preprocess_HOOK() for node.html.twig.
 */
function mytheme_preprocess_node(&$variables) {
   $uid = \Drupal::currentUser()->id();
   $author_id = $variables['node']->getOwner()->id();
   if ($author_id == $uid) {
     $variables['is_author'] = TRUE;
   }
   else {
     $variables['is_author'] = FALSE;
   }
}
1
  • Thank you Jimmy! Thank you Kevin! Jimmy's solution works!
    – Basic
    Dec 24, 2018 at 6:57
1

The problem with your approach and Jimmy's answer is, that in production with Drupal's default caching this won't work. The snippet that you placed in the preprocess function simply gets cached after the first execution until you manually rebuild Drupal's cache.

To reproduce it simply create two new users, open two anonymous browser windows and in each log in as one of the users. With the first user create a node and rebuild the cache with drush cr. "You are node author" will be displayed. Fine. But now in the second browser window logged in as the second user visit the node and you will also see "You are node author". Bad. Only after drush cr and a refreshed browser window you'll see "You are not node author". Same now when you get back to the first user and refresh the browser window, you'll see "You are not node author". Until you rebuild the cache again.

What you could do now to solve the problem is to provide a render array instead and take control of its cache contexts.

In your node template put:

{{ foobar }}

And in your theme file put:

/**
 * Implements hook_preprocess_HOOK() for node.html.twig.
 */
function MYTHEME_preprocess_node(&$variables) {

  $variables['foobar'] = [
    '#markup' => '',
    '#cache' => [
      'contexts' => [
        // As we need this piece of markup to be user-sensitive
        // we tell Drupal to vary the output by the 'user' cache context.
        'user',
      ],
    ]
  ];

  // The rest of the logic can stay basically the same.
  $uid = \Drupal::currentUser()->id();
  $author_id = $variables['node']->getOwner()->id();
  if ($author_id == $uid) {
    $variables['foobar']['#markup'] = t('You are node author');
  }
  else {
    $variables['foobar']['#markup'] = t('You are not node author');
  }
}

For more info see Cacheability of render arrays from where I've taken the sample.


Note that with advanced server-side caching (Varnish etc.) this approach still won't work. It then needs to get Ajaxified.

2
  • This seems like more of a back office thing to boot - not sure of the value of having this in the front end theme where it could 'leak' out in one of the various ways you mentioned.
    – Kevin
    Dec 26, 2018 at 5:44
  • 1
    @Kevin – Not sure what you mean, but OP uses preprocess and template, so it‘s on theme level, no matter if backend or frontend, the cache needs to get busted.
    – leymannx
    Dec 26, 2018 at 6:43

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.