2

I'm rendering an array whose URL is dependent on a $_GET variable.

Where the variable is present and valid, I want to serve an iframe with the _GET variable as part of the URL. At the moment the cache is capturing the variable and preventing different value being passed to the page.

In my module I have this:

function MY_MODULE_preprocess_paragraph__iframe(&$variables) {
    $query = @$_GET['e'];
    /*...*/
}

But the value $query is staying the same until the caches are cleared.

Is there a better way of capturing the $_GET variable, or a way of preventing the value from being cached?

4
  • 3
    You can't turn off caching for a paragraph (at least not in prod). You need a cache context for the query parameter. If you have a lot of variations you could add a placeholder with a lazy builder callback. Then the cache context doesn't create a new cache entry for the paragraph and the parent entity whenever the GET variable changes.
    – 4uk4
    May 11, 2021 at 8:55
  • What's a lazy builder callback? Is it implemented in a preprocess hook? May 11, 2021 at 8:59
  • 1
    Yes, you could meet the auto-placeholdering conditions, for example max-age=0. Or set #create_placeholder, see drupal.stackexchange.com/a/271124/47547
    – 4uk4
    May 11, 2021 at 11:21

1 Answer 1

1

Declare the dependency on the GET parameter with a cache context:

/mymodule/mymodule.module

function mymodule_preprocess_paragraph(&$variables) {

  $foo = \Drupal::request()->query->get('foo');
  $variables['content']['foo'] = [
    '#markup' => "foo = $foo",
    '#cache' => ['contexts' => ['url.query_args:foo']],
  ];
}

More info https://www.drupal.org/docs/drupal-apis/cache-api/cache-contexts

However, if you have more than a few possible values of foo this is a problem with cache performance, especially for nested entities like paragraphs. Each value creates a new cache entry for the paragraph and its parent entities.

To avoid this put a placeholder in the paragaph:

/mymodule/mymodule.module

function mymodule_preprocess_paragraph(&$variables) {
  
  $variables['content']['foo_placeholdered'] = [ 
    '#lazy_builder' => ['\Drupal\mymodule\MymoduleLazyBuilders::getFoo', []],
    '#create_placeholder' => TRUE,
  ];
}

and build the content which depends on the GET parameter in a lazy builder:

/mymodule/src/MymoduleLazyBuilders.php

<?php

namespace Drupal\mymodule;

use Drupal\Core\Render\Element\RenderCallbackInterface;

class MymoduleLazyBuilders implements RenderCallbackInterface {

  public static function getFoo() {
    $foo = \Drupal::request()->query->get('foo');
    return  [
      '#markup' => "foo = $foo",
      '#cache' => ['contexts' => ['url.query_args:foo']],
    ];
  }

}

For time consuming calculations such placeholders can be delivered through BigPipe. So if you enable this module you can also improve page speed.

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.