web-dev-qa-db-ja.com

カスタムブロッククラス、カスタムテンプレート、キャッシュの問題

私のウェブサイトにカスタムブロックを追加する必要があります。このブロックには、(税関フィールドからの)一部のユーザー値を表示する必要があります。

必要なすべてのユーザー変数を表示できますが、何らかの理由でユーザー値が変更された場合は、カスタムブロックが表示されているページからニュース値を取得するためにすべてのキャッシュをクリアする必要があります。

drupal 8キャッシュAPIを確認し、いくつかの例を見つけてみましたが、変数がキャッシュされていない(またはキャッシュされているが、ユーザーがデータを変更したときに更新する)場合の方法がわかりません)

私のコードは非常に単純です、(私の.moduleに)このフックのテーマがあります:

function main_menu_theme($existing, $type, $theme, $path)
{
  $theme=array();
  $theme['block__main_menu_quick_stat_block'] = array(
    'base hook' => 'block',
    // 'render element' => 'block', // I tried with and without this line..
  );
  return $theme;
}

これは私のブロッククラスからのビルドメソッドです:

class MainMenuQuickStatBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $build = [];

    // Get the currect Drupal User
    $user = _getCurrentUser();

//I tried this...
//  $build['main_menu_quick_stat_block'] = array(
//    '#one' => $user->customfieldone->value,
//    '#two' => $user->customfieldtwo->value,
//  );
//  return $build;

//I tried this...
//    return array(
//      'main_menu_quick_stat_block' => array(
//        '#cache' => array('max-age' => 0),
//        '#one' => $user->customfieldone->value,
//        '#two' => $user->customfieldtwo->value,
//      ),
//    );

//Last try..  
    return array(
        '#one' => $user->customfieldone->value,
        '#two' => $user->customfieldtwo->value,
        '#cache' => [
          'max-age' => 0,
          // 'contexts' => ['user',], // I tried this
          // 'contexts' => 'user', // I tried this
        ],
    );
  }
}

私のカスタムテンプレートでは、デフォルトのblock.html.twigテンプレートをテーマディレクトリからコピーしました。カスタムテンプレートのおかげで、Webページから変数「1」と「2」を表示できます。しかし、これらの変数を構成できず、キャッシュできなくなります!

私もキャッシュタグを試してみましたが、成功しません。

EDIT 1(4k4詳細回答の後!)

これが私の最後の試みです:カスタムブロッククラスから:

class MainMenuQuickStatBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $build = [];
    $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());

    //$user = \Drupal::currentUser(); // If I use this way, I get this error in the "'tags' => $user->getCacheTags()," below : "Error: Call to undefined method Drupal\Core\Session\AccountProxy::getCacheTags() in Drupal\main_menu\Plugin\Block\MainMenuQuickStatBlock->build() (line 52 of modules/custom/main_menu/src/Plugin/Block/MainMenuQuickStatBlock.php)."

    $var1 = $user->field_field1->value; //If a log var1, I get a value here ($var1 = 7 by example)
    $var2 = 42; //its a test

    return [
        '#theme' => 'block__main_menu_quick_stat_block',
        '#test' => 42,
        '#var1' => $var1,
        '#cache' => [
          'contexts' => ['user'],
          'tags' => $user->getCacheTags(),
        ],
    ];
  }
}

私の.moduleファイルから:

...
function main_menu_theme($existing, $type, $theme, $path)
{
  $theme=array();
  $theme['block__main_menu_quick_stat_block'] = array(
    'variables' => [
      'var1' => NULL,
      'test' => NULL,
    ],
  );

  return $theme;
}

キャッシュをクリアしました(drush cr)

ページを読み込むときにカスタムテンプレートブロックが呼び出されますが、変数「var1」と「test」がnullです。以下では、カスタムテンプレートで「{{kint()}}」を使用して変数の配列をログに記録します。

enter image description here

drupal私の変数がnullである理由を知るためのガイドを見つけます...

2
matthieu lopez

問題は、キャッシュパラメータの選択ではありません。 cache max-ageを0に設定した場合、キャッシュを無効にするために他のキャッシュ設定は必要ありません。

問題は、ブロックテンプレートの使用方法です。おそらく、追加した単一の変数のみをレンダリングし、デフォルトの{{ content }}変数はレンダリングしません。これが、キャッシュ情報が失われる理由です。

カスタム変数のカスタムtwigテンプレートを使用することをお勧めします。

hook_theme()in mymodule.module:

function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'mytemplate' => [
      'variables' => [
        'var1' => NULL,
        'var2' => NULL,
      ],
    ],
  ];
}

build()in block class:

  public function build() {

    $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
    $var1 = $user->field_field1->value;
    $var2 = $user->field_field2->value;

    return [
      '#theme' => 'mytemplate',
      '#var1' => $var1,
      '#var2' => $var2,
      '#cache' => [
        'contexts' =>  ['user'],
        'tags' => $user->getCacheTags(),
      ],
    ];
  };

mytemplate.html.twig:

<h2>Additional user info</h2>
<p>Field 1: {{ var1 }}</p>
<p>Field 2: {{ var2 }}</p>

テンプレートmytemplateは、ブロックテンプレート内にネストされます。テンプレートをデフォルトに戻すと、キャッシュデータをブロックレベルと上位レベルのページ要素にマージできます。

4
4k4

キャッシュを完全に無効にすることで、何をすべきかを理解する必要があります。

'tags' => $ user-> getCacheTags()を使用すると無効化できますが、それも必要ですが、デフォルトでは、ブロックにアクセスする最初のユーザーに対してブロックがキャッシュされます。したがって、追加で必要なのは 'contexts'] => ['user']で、各ユーザーが独自のキャッシュを必要とすることを示します。

また、ブロックにメソッドgetCacheTags()、getCacheMaxAge()、およびgetCacheContexts()を実装することもできますが、何も変更しないでください。

PS:_getCurrentUser()のようなグローバル関数を定義しないでください。常にmain_menu_get_current_user()のようなモジュールをプレフィックスにするか、それらをクラスの一部にします(たとえば、再利用する場合はトレイトを使用します)。

2
Berdir