メニューリンクのタイトルを変更するにはどうすればよいですか?


8

私のウェブサイトでは、ユーザーは時間の経過とともにいくつかの「ポイント」を収集できます。いくつかのリンク(「ホーム」、「プロファイル」、「ログアウト」など)を含むトップバーメニューがあります。メニュー項目「プロファイル」を変更し、現在接続しているユーザーが所有するポイントを追加したい。

私はいくつかのフックを試しましたが、私が望んでいたものを得るのにほぼ成功しましたhook_link_alter()

function mycustommodule_link_alter(&$variables) {
  if ($variables['text'] == "profile") {
    // Do some work.
    $variables['text'] = $variables['text'] . " (you have $nb_points points)";
  }
}

(を使用してdrush cr)キャッシュをクリアしました。メニュー項目に必要な値が表示されます。ただし、なんらかの理由で値が変更された場合は、古い値が表示されます。値を更新するには、常にキャッシュをクリアする必要があります。

ユーザーから獲得したポイントが変わるたびにメニュータイトルを更新するためにキャッシュを消去しないようにするにはどうすればよいですか?


これにはカスタムプラグインが必要なようです。興味深い質問です。一般に、D8に古いフックを実装することは避けてください。問題は、カスタムプラグインを介してメニュータイトルを変更する方法です。
Codium

メニューはブロックになっていますか?その場合は、そのブロックのキャッシュを0に設定してみてください
pbonnefoi

これは、管理インターフェースから作成されたブロックです。私はキャッシュ構成にアクセスしませんでした:)
matthieu lopez

drupal.org/docs/8/api/menu-apiから始めることをお勧めします。'#cache' => ['max-age' => 0]は解決策ではありません。動的メニューリンクを作成する必要があります。
ArnoldPÉTER16年

「メニュー項目に欲しい値が表示されています」他のユーザーアカウントでメニューを確認しましたか?すべてのユーザーに同じ数のポイントが表示されていると思います。
ya.teck

回答:


7

カスタムメニューリンクプラグインを実装することをお勧めします。以下のコードは、モジュール名が例であると想定しています。

<?php

namespace Drupal\example\Plugin\Menu;

use Drupal\Core\Database\Connection;
use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * A menu link that displays number of points.
 */
class ExampleMenuLink extends MenuLinkDefault {

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $dbConnection;

  /**
   * Constructs a new points menu link.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Menu\StaticMenuLinkOverridesInterface $static_override
   *   The static override storage.
   * @param \Drupal\Core\Database\Connection $db_connection
   *   The database connection.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, Connection $db_connection) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);
    $this->dbConnection = $db_connection;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('menu_link.static.overrides'),
      $container->get('database')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getTitle() {
    $count = $this->dbConnection->query('SELECT COUNT(*) FROM {example_points}')->fetchField();
    return $this->t('You have (@count) points', ['@count' => $count]);
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    // Invalidate these tags when number of points is changed.
    return ['example.points_count'];
  }

}

データベースサービスを注入したくない場合は、クラスがはるかに単純になります。

<?php

namespace Drupal\example\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * A menu link that displays number of points.
 */
class ExampleMenuLink extends MenuLinkDefault {

  /**
   * {@inheritdoc}
   */
  public function getTitle() {
    $count = \Drupal::database()->query('SELECT COUNT(*) FROM {example_points}')->fetchField();
    return $this->t('You have (@count) points', ['@count' => $count]);
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    // Invalidate these tags when number of points is changed.
    return ['example.points_count'];
  }

}

次に、リンク定義をexample.links.menu.ymlファイルに配置する必要があります。

example.user_points:
  route_name: <front>
  menu_name: main
  class: Drupal\example\Plugin\Menu\ExampleMenuLink
  weight: 30

キャッシングの問題

ポイントの数が変更されるたびに、メニューリンクキャッシュは次のように無効化されます。

 \Drupal::service('cache_tags.invalidator')->invalidateTags(['example.points_count']);

このための適切な場所を見つける必要があります。提供されたモジュールによって管理されているポイントがモジュールAPIを確認し、適切なフック(hook_points_insert()hook_points_delete()など取得する場合

ポイント数はユーザーアカウントごとに個別に計算されるため、アカウントごとのキャッシュタグ(など['example.points_count.' . $uid])の使用を検討してください。したがって、ポイントは変更されていないユーザーのキャッシュが保持されます。


メニューリンクプラグインのコードを生成するために、Drupalコードジェネレーターを使用しました。


この回答は適切です(現在の公式ドキュメントよりも役立ちます。ただし、yamlファイルの名前はexample.links.menu.ymlとし、example.menu-links.ymlは含めないでください。その後、キャッシュとメニュー項目をクリアしてください表示されます。
Sut3kh

これはgetRouteParameters()メソッドもオーバーライドすることは可能ですか?いいえの場合、どのようにroute_parametersを動的に変更できますか?私の場合、ルーティングに{user}があり、メニューリンクは現在のユーザーのユーザーIDとしてユーザーIDを動的に提供する必要があります。
Igal

@イガルはそれが可能だと思います。
ya.teck 2017年

2

私も同じ問題に直面しました。メニュー項目はキャッシュされるため、キャッシュをクリアするまで常に古い値が表示されます。別の方法は、を使用してhook_page_attachments()ポイントをdrupalSettings.YOUR_MODULE_OR_THEME.YOUR_VARIABLEにアタッチし、JavaScriptでそれらにアクセスして、ブラウザーでレンダリングすることです。

通常の方法では、サイトのパフォーマンスで「プロファイル」メニューが表示されるたびに、ページのキャッシュを無効にします。


0

0にhook_preprocess_menu()設定$variables['#cache']['max-age']して、そのメニューのキャッシュを無効にします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.