web-dev-qa-db-ja.com

複数のユーザーとロールでキャッシュを共有するにはどうすればよいですか?

私のカスタムモジュールでは、高価な操作を実行するカスタムブロックを定義します。

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  $agent_number = get_agent_number_from_context();
  return [
    '#theme' => 'my_custom_module',
    '#cache' => [
      'keys' => ['my_block', 'full_version', $agent_number],
      'tags' => ['my_custom_module'],
      'max-age' => 86400,
    ],
  ];
}

キャッシングは、別のユーザーがブロックを表示したり、別の役割を持つユーザーがページを表示したりする場合を除いて機能します。新しいキャッシュアイテムを作成します。複数のユーザー/ロールに対して一度だけキャッシュを設定することは可能ですか?

編集

私は以下を試しました(問題に別の変数を追加しないためにrouteコンテキストを使用することになりました):

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  return [
    '#theme' => 'my_custom_module',
    '#data' => $data,
    '#cache' => [
      'contexts' => ['route'],
      'tags' => ['my_module'],
      'max-age' => 86400,
    ],
  ];
}

ページマネージャーを介してレイアウトビルダーを使用してブロックを作成したときに、cache_renderテーブルにアイテムが追加されなかったことに注意してください(別の問題である可能性があります)。デフォルトでブロックを追加したときDrupalブロックレイアウトで、すべてのユーザーに対して新しいキャッシュレコードがまだ作成されていることに気付きました。たとえば、

ユーザー1が/ my-account/A123に移動し、次のレコードがcache_renderテーブルに追加されました。

cid

entity_view:block:mycustomblock:[languages:language_interface]=en:[route]=entity.node.canonical7ccb4f15749b8c9e759f0016bfc863bd5e6bef88ea0a9dfe7b1cbe2687d30b32:[theme]=my_theme:[url.site]=http://mysite.test:[user]=1

タグ

block_view config:block.block.mycustomblock config:user.role.administrator config:user.role.authenticated my_module rendered user:1

ユーザー72が/ my-account/A123に移動し、次のレコードがcache_renderテーブルに追加されました。

cid

entity_view:block:mycustomblock:[languages:language_interface]=en:[route]=entity.node.canonical7ccb4f15749b8c9e759f0016bfc863bd5e6bef88ea0a9dfe7b1cbe2687d30b32:[theme]=my_theme:[url.site]=http://mysite.test:[user]=79

タグ

block_view config:block.block.mycustomblock config:user.role.agent config:user.role.authenticated my_module rendered user:79

コンテキストを使用すると、すべてのユーザーの新しいレコードが作成されることがわかります。

編集

ページマネージャーの外部でブロックを機能させようとしたため、テストフォームEdit 2は無効だと思いますが、ログインしたユーザーを使用するようにページマネージャーからのコンテキストが必要でした。簡単に言えば、ページマネージャーまたはレイアウトマネージャーを使用しているときに、(キーキャッシュは機能しているが)コンテキストキャッシュが機能しない理由を理解する必要があります。

3
albertski

userや_user.roles_などのキャッシュコンテキストを追加しない限り、キャッシュはデフォルトで複数のユーザーまたはロールと共有されます。

それ以外の場合、問題のコードが達成したいことを伝えるのは困難です。

  1. ブロックキャッシュキーを設定する必要がある場合は、ここから行うことはできず、必要もありません。自動的に設定されます。 get_agent_number_from_context()はおそらくカスタム_cache_context.agent_number_である必要があります。これをブロックビルド配列に追加して、この変数によってキャッシュされたブロックを変更できます。

    _/**
     * {@inheritdoc}
     */
    public function build() {
      $data = get_expensive_data();
      return [
        '#theme' => 'my_custom_module',
        '#data' => $data,
        '#cache' => [
          'contexts' => ['agent_number'],
          'max-age' => 86400,
        ],
      ];
    }
    _

    カスタムキャッシュコンテキストを作成する方法: https://www.drupal.org/docs/8/api/cache-api/cache-contexts#recognize-discover-create

  2. 高価なデータを独自にキャッシュしたい場合(レンダリングされた結果を必ずしもブロックではない他の場所で再利用したい場合に意味があります)、_#pre_render_でget_expensive_data()を実行する必要がありますキャッシュヒットの場合に実行されないようにするコールバック。 https://dev.acquia.com/blog/drupal-8-performance-render-caching を参照してください

編集1:質問に追加したCIDには、ユーザーのキャッシュコンテキストが含まれています。これまでに示したコードでは、ブロック内でどのように終わるかわかりません。しかし、ユーザーのキャッシュタグもあるので、現在のユーザーを取得してレンダリングするコードが必要です。

編集2:テーマが同じであるとすると、userが削除されたため、おそらくすべてのレンダーキャッシュにデフォルトの_user.permissions_キャッシュコンテキストが存在します。 https://www.drupal.org/project/drupal/issues/24930 を参照してください

5
4k4