0

I've spent days trying to figure this out and really hope you guys can help me out here.

Let's say, I’ve created a list field on the user entity called field_render_array with the options:

  • Render array 1
  • Render array 2

There is a controller called RenderArray which should:

  • Return render array 0 if field_render_array is not set.
  • Return render array 1 if field_render_array is equal to render_array_1.
  • Return render array 2 if field_render_array is equal to render_array_2.

I’ve been trying to achieve this using a controller like:

<?php

namespace Drupal\example\Controller;

use Drupal\Core\Controller\ControllerBase;

class RenderArrayController extends ControllerBase {

  public function content() {
    $user = \Drupal::currentUser();
    $field_render_array = $user->get(‘field_render_array’)->value;

    if (!isset($field_render_array)) {
      return array(
        ‘#markup' => ‘You haven’t set your preferred render array.',
      );
    }
    else if ($field_render_array == ‘render_array_1’ ) {
      return array(
        ‘#markup' => ‘Your preferred render array is 1',
      );
    }
    else {
      return array(
        ‘#markup' => ‘Your preferred render array is 2’,
      );
    }
  }

}

The problem is that the value of $field_render_array is getting cached. This comes across as a bug for end-users as the render array doesn’t immediately change after changing the value of field_render_array.

Is it possible to somehow avoid certain variables from being cached or is there another solution to achieve the same thing?

1
  • Google "drupal 8 lazy builder".
    – user21641
    Nov 27, 2016 at 13:48

2 Answers 2

3

If the variables come from the current user, then add this cache context to the build array you return:

$build['#cache']['contexts'][] = 'user';
1
  • 2
    See drupal.org/docs/8/api/render-api/cacheability-of-render-arrays for lots of documentation. Note that this means that your controller will possibly have a huge amount of variations, one for each user. If it is not expensive to build, you might want to disable caching completely with #cache max-age = 0. If it is expensive and you have a lot of users, you could make your own cache contexts that doesn't vary by user ID but just by the value of that field. You just need a service, see drupal.stackexchange.com/questions/214144/…
    – Berdir
    Nov 27, 2016 at 14:31
0

To solve this problem I decided to reduce the number of render array's from 3 to 1.

<?php

namespace Drupal\example\Controller;

use Drupal\Core\Controller\ControllerBase;

class RenderArrayController extends ControllerBase {

  public function content() {
    $user = \Drupal::currentUser();
    $field_render_array = $user->get('field_render_array')->value;

    if (!isset($field_render_array)) {
      $markup = 'You haven’t set your preferred render array.';
    }
    else if ($field_render_array == 'render_array_1' ) {
      $markup = 'Your preferred render array is 1';
    }
    else {
      $markup = 'Your preferred render array is 2';
    }

    return array(
      '#markup' => $markup,
      '#cache' => ['max-age' => 0],
    );

  }

}

As the field_render_array can always change, I added '#cache' => ['max-age' => 0] to the render array left. See https://www.drupal.org/docs/8/api/render-api/cacheability-of-render-arrays for more information.

Your Answer

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

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