3

I have a custom block that display some information from a custom configuration form. I want the block to be cached, however, I want the block cache to be cleared every time I save the form.

I would like to do this in the submitForm function. How do I go about and do this?

1
  • There are multiple answers for how to prevent the block from being cached, but I want it to be cached. Just need to know how to invalidate the cacheing of my custom block
    – iStryker
    Commented Jun 25, 2020 at 12:39

2 Answers 2

8

When displaying information from a config object add it also as cache dependency to the render array.

For example in a preprocess hook:

  $config = \Drupal::config('mymodule.settings');
  $config_value = $config->get('some_field');
  $variables['some_field'] = [
    '#markup' => $config_value,
  ];
  // add the cache tag, so that the output gets invalidated when the config is saved
  \Drupal::service('renderer')->addCacheableDependency($variables, $config);

See How to clear cache for config entity after making changes?

You don't need to change form submit because saving a config object automatically invalidates cache entries having this cache dependency (cache tag).


Another example based on the block code from your answer and using a different method to add the cache tag:

  /**
   * Config settings.
   *
   * @var string
   */
  const SETTINGS = 'uw_cbl_special_alert.settings';
  /**
   * {@inheritdoc}
   */
  public function build() {
    $config = \Drupal::config(static::SETTINGS);
    return [
      '#markup' => $config->get('message'),
      '#cache' => [
        'tags' => $config->getCacheTags(),
      ],
    ];
  }

Access caching

As asked in the comments, you can add cache dependencies to access results as well:

AccessResult::allowed()->addCacheableDependency($config)
AccessResult::forbidden()->addCacheableDependency($config)
4
  • The relevant cache tag in this instance is config:my_module.settings. See Cache tags on d.o.
    – sonfd
    Commented Jun 25, 2020 at 12:48
  • As a note, in case it's unclear, if you're building your custom block with your own plugin, you can add the cache dependencies in your build() method.
    – sonfd
    Commented Jun 25, 2020 at 13:53
  • Your 2 examples do work for the message field, however, they do not work for my blockAccess. My answer does. Hope you can read this... protected function blockAccess(AccountInterface $account) { $config = \Drupal::config(static::SETTINGS); $display = $config->get('display_option'); if ($display) return AccessResult::allowed(); } return AccessResult::forbidden();}
    – iStryker
    Commented Jun 25, 2020 at 17:39
  • Thanks for adding to Answer. It works!
    – iStryker
    Commented Jun 25, 2020 at 18:18
-2

Ok I believe I figured it out. This works for me.

use Drupal\Core\Cache\Cache;
class ConfigurationForm extends ConfigFormBase {
  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Invalidate block cache.
    Cache::invalidateTags(['config:block.block.{block_id_tag}']);
  }
}

I had to search the cachetags table in the database to find the block id tag.
In my case my custom block id in the annotation was uw_cbl_special_alert but the block id tag was specialalert

In case you are interested, code snippet from custom block

  /**
   * Config settings.
   *
   * @var string
   */
  const SETTINGS = 'uw_cbl_special_alert.settings';
  /**
   * {@inheritdoc}
   */
  public function build() {
    $config = \Drupal::config(static::SETTINGS);
    // Turn caching off as this is a special message and show never be cached.
    return [
      '#markup' => $config->get('message'),
    ];
  }
1
  • 4
    This is not a good way to do this. You should use the method in 4k4's answer.
    – sonfd
    Commented Jun 25, 2020 at 14:22

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.