I have a custom module with a block plugin:
SliderBlock.php
class SliderBlock extends BlockBase {
public function build() {
$build = [];
$build['#theme'] = 'slider_block';
return $build;
}
}
I want to render a list of nodes of type 'slides' in the block (it will eventually be a custom slider feature)
mymodule.module
function mymodule_theme() {
return [
'slides_block' => [
'variables' => [
'slides' => get_slides(),
],
],
];
}
function get_slides() {
// Load all slides nodes.
$nids = \Drupal::entityQuery('node')
->condition('type','slides')
->condition('status','1') // Only published slides nodes.
->execute();
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
return $nodes;
}
and I loop over each in the template to get the markup I need:
slider-block.html.twig
{# markup for slider here #}
{% for slide in slides %}
<p>{{ slide.label }}</p>
{% endfor %}
The above template shows me the title field for each Slides node, which is what I expect. The problem is that if I un-publish a Slides node, the markup is not updated unless I clear caches.
Alright, this sounds like a cache issue, so I dove into a google search mission and discovered a series of ways to disable caching for the block. None of which seem to work, for anonymous users or otherwise:
// Unsuccessful:
public function getCacheMaxAge() {
return 0;
}
// Unsuccessful:
$build['#cache'] = [
'max-age' => 0,
];
I looked at cache contexts, as far as I could tell, there was no 'node' based cache context. If I understood them correctly, cache tags wouldn't help, since I don't know the ids of any given node of type 'Slides'.
I 'only want to' disable caching for this block. This block will be rendered only on a specific page, so I could disable caching on that page using the modules route yml file (am I right?), but it feels wrong to disable that whole page for the sake of one block.
What is the right way to solve this, and what's the methodology in reaching that conclusion?
Note: I could use views to collect the nodes, but to customise the view markup is more challenging.
node_list
would do it, but it would also invalidate the cache when any node was created or updated, not just ones that would be involved in the slider. If you need to get more granular, use your own custom cache tag, and implementhook_node_insert
etc to invalidate it under the right conditions (probably content type == slider)