如何通过钩子与事件自定义区块缓存标签并实现缓存失效?
Drupal区块交替显示与自定义缓存标签失效控制问题
需求与现状
- 不依赖区块可见性插件,实现同一页面区块交替显示(例:首页依次显示A→B→C→循环)
- 用自定义缓存标签精准控制缓存失效,避免全局缓存清除
- 当前关闭缓存或全局失效时功能正常,但自定义缓存标签无法被正确获取,导致无法针对性失效缓存
问题核心细节
在hook_block_view_alter()钩子中为区块注入自定义缓存标签(选择该钩子的原因:更早的钩子中区块ID未生成,且区块显示逻辑在hook_block_access()中判断,需提前完成缓存标签设置)。但在kernel.finish_request事件订阅器中,通过$block->getCacheTags()或$block->getCacheTagsToInvalidate()无法获取到这些自定义标签,无法实现针对性缓存失效。尝试过多个区块钩子及kernel.request事件,仅kernel.finish_request能实现全局失效,但无法利用自定义标签。
现有代码片段
模块文件中的hook_block_view_alter实现
// In the .module file... /** * Implements hook_block_view_alter(). */ function my_module_block_view_alter(array &$build, BlockPluginInterface $block) { // 3rd hook to get called in the block hooks if (array_key_exists('#id', $build) ) { $ci = MyController::getInfo($build['#id']); if ($ci['CanControl'] !== []) { $controlId = &$ci['CanControl']['id']; $build['#cache']['tags'][] = $controlId; $build['#cache']['tags'][] = "$controlId:$build[#id]"; } } }
kernel.finish_request事件订阅器代码
// In an event subscriber module off the kernel.FinishRequest event. class BlockCacheManager implements EventSubscriberInterface { // EVENT SUBSCRIBER STUFF THEN... public function kernelFinishRequest(Event $event) { // Ignore AJAX calls if (!Drupal::request()->isXmlHttpRequest()) { // CODE THAT GETS THE RELEVANT BLOCK IDs THEN... $blocks = Block::loadMultiple($blockIds); $tags = []; foreach ($blocks as $block) { $bTags = $block->getCacheTagsToInvalidate(); // 自定义标签不在这 $bTags2 = $block->getCacheTags(); // 也不在这 $tags = array_merge($tags, $block->getCacheTagsToInvalidate()); } // 下面是期望实现的逻辑,但因为获取不到自定义标签无法执行 foreach ($blockIds as $blockId) { $cacheTags[] = "$controlId:$build[#id]"; } } } }
解决诉求
- 优先通过调整现有代码解决自定义缓存标签无法被获取的问题
- 也接受其他可行的替代方案
内容的提问来源于stack exchange,提问作者Reg
相关产品推荐
相关产品推荐

