Question

This is the first time I'm using the preprocees hook, apologies in advance.

I added a placeholder, {{user-uid}}, in a custom block body field, <a href="advisor/{{user-uid}}">Advisor Page</a></h5>.

My code is very simple, I have this hook theme.

    function boostrap_kampuster_preprocess_block(&$variables) {
        if (isset($variables['content']['#block_content'])) {
            $content = $variables['content']['#block_content'];
            
            /** custom block ID is 4 **/
            if( method_exists($content,'id') && $content->id() == '4') {
    
                $body = $variables['content']['body'][0]['#text'];
                
                $vars['user'] = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
                $body=str_replace('{{user-uid}}',$vars['user'],$body);
            }
        }
    }

I am not getting any errors but the function is not doing what it is supposed to do and replace {{user-uid}} with logged in user's ID either.

FYI, I cleared caches several times.

Was it helpful?

Solution

Recommend using @4k4's answer instead.

There are a few issues here:

  1. You're setting your $body variable, but not setting the change in your $variables array. You can fix this by using a reference, update with $body = &$variables['content']['body'][0]['#text'];
  2. You're replacing with the user object rather than the user id. You can't insert an object into the middle of a string. You can get the id of the current users with just \Drupal::currentUser()->id().
  3. I'd recommend not setting the current user to $vars['user'] in a preprocess function when you're using $variables as the accepted parameter. It's pretty common to use $vars as a shorthand in a preprocess $variables function and randomly setting $vars['user'] here is definitely going to cause confusion for anyone reading this in the future.
  4. I'd also recommend not using {{ VARIABLE }} as a custom placeholder since D8 templates use twig and that is twig syntax. For the same reasons you wouldn't use <?php echo $VARIABLE; ?> as your custom placeholder.

Your code updated:

function boostrap_kampuster_preprocess_block(&$variables) {
  if (isset($variables['content']['#block_content'])) {
    $content = $variables['content']['#block_content'];
        
    /** custom block ID is 4 **/
    if( method_exists($content,'id') && $content->id() == '4') {
      // These lines updated.
      $body = &$variables['content']['body'][0]['#text'];
      $body = str_replace('{{user-uid}}', \Drupal::currentUser()->id(), $body);
      // As 4k4 pointed out - you must set a cache context or this won't work as expected.
      $variables['#cache']['contexts'][] = 'user';
    }
  }
}

OTHER TIPS

In addition to @sonfd answer you also need to consider caching. The easiest way would be to add a cache context:

$variables['#cache']['contexts'][] = 'user';

But then the database needs to store a cached version for each user.

Better for performance would be to postpone replacing the placeholder by attaching a lazy builder to the render array:

function mytheme_preprocess_block(&$variables) {
  $variables['#attached']['placeholders']['{{user-uid}}'] = [
    '#lazy_builder' => ['_mytheme_replace_uid', []],
  ];
}

which then returns the markup of the user UID:

function _mytheme_replace_uid() {
  return [
    '#markup' => \Drupal::currentUser()->id(),
    '#cache' => ['contexts' => ['user']],
  ];
}

Drupal 9

Drupal 9 requires using only trusted callbacks. So define a class implementing TrustedCallbackInterface or RenderCallbackInterface:

mytheme/src/MythemeLazyBuilders.php:

<?php

namespace Drupal\mytheme;

use Drupal\Core\Render\Element\RenderCallbackInterface;

class MythemeLazyBuilders implements RenderCallbackInterface {

  public static function replaceUid() {
    return [
      '#markup' => \Drupal::currentUser()->id(),
      '#cache' => ['contexts' => ['user']],
    ];
  }

}

and add it to the render array:

function mytheme_preprocess_block(&$variables) {
  $variables['#attached']['placeholders']['{{user-uid}}'] = [
    '#lazy_builder' => ['\Drupal\mytheme\MythemeLazyBuilders::replaceUid', []],
  ];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top