ページごとに固有でなければならないブロックがログアウトしたユーザーのものではないという問題に遭遇しました。問題は、カスタムフィルターを含むビュー検索ページにあるカスタムブロックプラグインです(公開されたフィルターのカスタム置換のようなものです。ブロックは/ 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()を追加していますか?