0

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?

  • 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 Jun 25 at 12:39
5

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)
| improve this answer | |
  • The relevant cache tag in this instance is config:my_module.settings. See Cache tags on d.o. – sonfd Jun 25 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 Jun 25 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 Jun 25 at 17:39
  • Thanks for adding to Answer. It works! – iStryker Jun 25 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'),
    ];
  }
| improve this answer | |
  • 3
    This is not a good way to do this. You should use the method in 4k4's answer. – sonfd Jun 25 at 14:22

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.