web-dev-qa-db-ja.com

クッキーを正しく使用する方法は? (小枝とキャッシュのコンテキスト)

現在のプロジェクトでは、以前にアクセスしたランディングページに応じてノードテンプレートを変更する必要があります。私の考えでは、訪問者がこれらのランディングページの1つにアクセスすると、Cookieが設定され、その後のノードテンプレートはそのCookieに応じて変更されます。

訪問者のエントリポイントとして機能する3つのビューページがあります。
myproject.com/tv
myproject.com/mobile
myproject.com/infopoint

テーマの前処理では、Cookieをチェック/設定し、テンプレート変数を割り当てています。 Twigテンプレートは、その変数に応じて小さな変更を行います:

function MYTHEME_preprocess(array &$variables, $hook) {
  $router = \Drupal::routeMatch();

  if ($route = $router->getRouteObject()) {
    $view_id = $route->getDefault('view_id');
    $display_id = $route->getDefault('display_id');
    $view_display_plugin = $route->getOption('_view_display_plugin_id');

    if ($view_id && $view_display_plugin === 'page') {
      if ($view_id == 'slide') {
        user_cookie_save(['device' => 'tv']);
        $variables['MYTHEME']['device'] = 'tv';
      }
      elseif ($view_id == 'tile' && $display_id == 'mobile') {
        user_cookie_save(['device' => 'mobile']);
        $variables['MYTHEME']['device'] = 'mobile';
      }
      elseif ($view_id == 'tile' && $display_id == 'infopoint') {
        user_cookie_save(['device' => 'infopoint']);
        $variables['MYTHEME']['device'] = 'infopoint';
      }
    }
  }

  // user_cookie_save prefixes all cookie names with 'Drupal.visitor.'
  if (isset($_COOKIE['Drupal.visitor.device']) && 
    in_array($_COOKIE['Drupal.visitor.device'], ['tv', 'mobile', 'infopoint'])) {
         // I'm doing design modifications in my Twig templates depending on this variable
        $variables['MYTHEME']['device'] = $_COOKIE['Drupal.visitor.device'];
    }
  }
}

Services.ymlでcookieキャッシュコンテキストをアクティブ化しました

parameters:
  renderer.config:
    required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions', 'url.site', 'cookies:Drupal.visitor.device']

私のTwigテンプレートには、次のような複数のコードがあります:

{% if MYTHEME.device == 'tv' %}
   <!-- code here -->
{% else %}
   <!-- other design here -->
{% endif %}

残念ながら、コードは実際には機能しません。エントリページでは、deviceテーマ変数は常に正しいですが、Cookieは更新されません(最初の非キャッシュヒットだけがCookieを設定するように見えます。Cookieとtwig変数が等しくありません。)ノードテンプレートで、テーマ変数がまったく正しく設定されていません。

上記のコードを機能させる方法はありますか?

PS:キャッシュを無効にする地理距離計算でビューが遅いため、キャッシュされたページを匿名ユーザーにも提供する必要があります。

2
Hudri

質問のコードを更新しました。コードは現在機能しています。それはほぼ完全でした、しかし私はいくつかの単純な間違いをしました:

  1. 適切なキャッシュコンテキストを提供する場合でも、_Internal page cache_モジュールを無効にする必要があります。 _Internal dynamic page cache_モジュールのみが許可されています。
  2. user_cookie_save()は、Cookie名の前に_Drupal.visitor._を付けます。これは、ブラウザーの開発コンソールにも表示される実際の名前です。ただし、PHPでCookie名を確認する場合、ドットとスペースはアンダースコアに変換されます。つまり、user_cookie_save(['mycookie' => 'some_value']);を使用すると、_Drupal.visitor.mycookie_の「実際の」名前でCookieが作成されますが、PHP
    • あなたのテンプレート/モジュールコードはチェックする必要があります
      if ($_COOKIE['Drupal_visitor_mycookie'])
    • また、services.ymlでアンダースコア名を使用する必要があります
      _required_cache_contexts: ['cookies:Drupal_visitor_device', '...other_stuff...']_
  3. Cookieの値を設定せず、同じリクエストで更新されたCookieの値を確認します。
    user_cookie_save(['mycookie' => 'new_value'])
    はクライアントブラウザのCookieをすぐに更新しますが、PHP
    if ($_COOKIE['Drupal_visitor_mycookie'])
    は以前のリクエストからの元の値を返します。
5
Hudri