我遇到了一个问题,即对于注销用户而言,每页应该唯一的一个块不适用。问题是我在视图搜索页面上拥有一个自定义块插件,该插件包含自定义过滤器(有点像自定义替换暴露的过滤器。通过/ admin / structure / block放置的块)。
根据我对Drupal 8的了解,我将缓存上下文添加到构建数组中:
public function build() {
$search_form = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\SearchForm');
return [
'search_form' => $search_form,
'#cache' => ['contexts' => ['url.path', 'url.query_args']]
];
}
但是看来这一定是不正确的,因为注销后,该块将在第一个视图上缓存,并且当url更改时,它没有显示该块的新版本。
我认为可能是导致问题的视图页面,但是即使我在视图页面上关闭了缓存,问题仍然存在。
我可以通过几种方式解决此问题,例如,使用preprocess_block挂钩:
function mymodule_preprocess_block__mycustomsearchblock(&$variables) {
$variables['#cache']['contexts'][] = 'url.path';
$variables['#cache']['contexts'][] = 'url.query_args';
}
但这让我感到困扰,我不能只是将缓存上下文放入块的构建数组中。
由于我的代码块扩展了BlockBase,因此我决定尝试使用getCacheContexts()方法,尤其是因为我看到核心中的某些模块正在这样做。
public function getCacheContexts() {
return Cache::mergeContexts(parent::getCacheContexts(), ['url.path', 'url.query_args']);
}
这也解决了这个问题,但是有趣的是,当我在预处理块函数中输出变量时,这些变量未显示在$ variables ['#cache'] ['contexts']中,但它们的确显示在$ variables ['elements中'] ['#cache'] ['contexts']
array:5 [▼
0 => "languages:language_interface"
1 => "theme"
2 => "url.path"
3 => "url.query_args"
4 => "user.permissions"
]
我试图通过构建函数弄清楚它是如何工作的以及为什么它不起作用。
在viewMultiple()函数中查看/core/modules/block/src/BlockViewBuilder.php,看起来它从实体和插件中提取了缓存标签:
'contexts' => Cache::mergeContexts(
$entity->getCacheContexts(),
$plugin->getCacheContexts()
),
因此,这说明了为什么将getCacheContexts()方法添加到我的块插件中,为什么会将上下文添加到我的块中。另外,在同一类中查看preRender方法,看起来它没有在块构建功能中使用缓存数组,这使我感到困惑,因为在Drupal 8中添加缓存的方法似乎是添加#cache元素来渲染元素。
所以我的问题是
1)是否将缓存上下文直接添加到块插件中的数组上而忽略了?
2)如果是这样,是否有办法解决,我们是否需要将其添加到构建数组的子元素中?
3)如果直接添加的上下文被忽略,是否在自定义模块中添加getCacheContexts()成为块插件的方法?