I've created a block via my own custom module.
The block configuration page (/admin/structure/block/manage/jssorsliderblock) allows the adding and removing of files (images), to a particular folder. These images are utilised by the block when it's displayed.
My problem is that clicking the 'Save changes' button, the file is correctly uploaded to the specified folder, however Drupal doesn't pick up the changes. Clearing the caches fixes this.
I currently just upload the files using an upload form field, which may not officially register the file with Drupal. If this is the case, then maybe that's why Drupal doesn't realise a file has been added to the folder.
SOLUTIONS?
1) Do I need to flush caches programatically when the 'Save changes' button is clicked? If so can I just flush the caches I need (i.e. the file caches)? How do I do that?
2) Is there a better way of uploading the files, so that Drupal doesn't need it's caches clearing? (maybe there's a better way).
I saw this code elsewhere in a core module (/core/modules/forum/src/Plugin/Block/ForumBlockBase.php
):
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return Cache::mergeContexts(parent::getCacheContexts(), ['user.node_grants:view']);
}
/**
* {@inheritdoc}
*/
public function getCacheTags() {
return Cache::mergeTags(parent::getCacheTags(), ['node_list']);
}
Do I need something like that? Although these seem to just register what needs changing in that particular module, when the cache is cleared from outside (i.e. passive connection). I need it to be active, i.e. when changes are made, the cache is cleared immediately for the items that have changed (in this case files being added to the public file space).
Thanks.
Comments
Drupal 8 caches render arrays
Drupal 8 caches render arrays, and until the cache is cleared for that render array (or all caches), the code will not update. You can clear the cache for the given render array (in your case, a block)
For example, I recently created a page that displays images from an instagram feed on the site. I used the getCacheTags() in my block plugin as follows:
So the relevant cache tag is: instagram_stream
I have a cron run that pulls the stream info from instagram on cron runs. If new images are found, I then clear the block cache (and the page cache that uses the same stream info) with:
So you will need to do two things:
1) Add cache tags to your block using getCacheTags()
2) Tie into the submit function on your block config page, and add a call that invalidates the cache tags for your block.
Cache not cleared by tag method
In the end I put
drupal_flush_all_caches();
into the Submit callback, which worked. The cache tags methods didn't seem to work for me, but then I don't fully understand yet. I even forced a cron, but still no change.I don't feel my
drupal_flush_all_caches()
route, is the right way forward. I really need to tell Drupal the bear-minimum cache clearance required.I need to read up on Drupal caching a lot more.
The code I tried was:
However it was only the following that worked:
Strange behaviour
Unfortunately it turns out that the
drupal_flush_all_caches()
call doesn't consistently clear the cache for me. Like I said, I need to do a lot more research on Drupal 8's caching system, as it relates to module development.The code you showed was
The code you showed was correct, however you have to note that it will not work until you clear the cache once, as the original build would not have had the cache tags applied in the cache. Try using that code again, but clear your cache.
Thanks Jaypan
Thanks.
I couldn't get this consistently working in the end. However I think it's because I didn't officially register the files with Drupal. The files were being uploaded by a 'file upload' (managed_file) user interface element. This will upload the file to the specified directory within Drupal, but I am not sure that it officially registers the file with Drupal.
Although clearing caches (drush cr, for example) will tell Drupal to scan directories for changes to files (new or otherwise).
I think I've found a better way to achieve what I need to do. The alternative is for the user to create some content (via a specified content type). I'm then hoping to be able to parse and display this content type from within my block code.
Thank you, Jaypan, for the
Thank you, Jaypan, for the getCacheTags() code! Saved my day!
Thank you, Jaypan! getCacheTags() works perfectly
I defined getCacheTags() inside my custom block and created a service to clear the cache using invalidateTags()