it-swarm.com.de

Wie ändere ich den Titel eines Menü-Links?

Auf meiner Website können Benutzer im Laufe der Zeit einige "Punkte" sammeln. Ich habe ein Menü in der oberen Leiste mit einigen Links (z. B. "Home", "Profil", "Abmelden"). Ich möchte den Menüpunkt "Profil" ändern und die Anzahl der Punkte hinzufügen, die dem aktuell verbundenen Benutzer gehören.

Ich habe mehrere Hooks ausprobiert und es ist mir fast gelungen, mit hook_link_alter() das zu bekommen, was ich wollte.

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

Ich habe den Cache geleert (mit drush cr) und der Menüpunkt zeigt den gewünschten Wert an. Wenn sich der Wert jedoch aus irgendeinem Grund ändert, wird der alte Wert angezeigt. Ich muss den Cache ständig leeren, um seinen Wert zu aktualisieren.

Wie kann ich vermeiden, den Cache zu bereinigen, um den Menütitel zu aktualisieren, wenn sich die vom Benutzer erzielten Punkte ändern?

8
matthieu lopez

Ich schlage vor, ein benutzerdefiniertes Menü-Link-Plugin zu implementieren. Der folgende Code setzt voraus, dass Ihr Modulname Beispiel ist.

<?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'];
  }

}

Wenn Sie den Datenbankdienst nicht einfügen möchten, wird die Klasse viel einfacher.

<?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'];
  }

}

Als nächstes müssen Sie die Linkdefinition in die Datei example.links.menu.yml Einfügen.

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

Das Caching-Problem

Immer wenn die Anzahl der Punkte geändert wird, sollte der Menü-Link-Cache wie folgt ungültig gemacht werden.

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

Sie müssen den richtigen Ort dafür finden. Wenn die vom beitragenden Modul verwalteten Punkte die Modul-API überprüfen und einen geeigneten Hook auswählen ( hook_points_insert (), hook_points_delete () und so weiter).

Da die Anzahl der Punkte für jedes Benutzerkonto einzeln berechnet wird, können Sie die Verwendung von Cache-Tags pro Konto in Betracht ziehen (etwa ['example.points_count.' . $uid]). Daher bleibt der Cache für Benutzer mit unveränderten Punkten erhalten.


Um Code für das Menü-Link-Plugin zu generieren, habe ich Drupal Code Generator verwendet.

7
ya.teck

Ich hatte das gleiche Problem. Die Menüelemente werden zwischengespeichert, sodass immer der alte Wert angezeigt wird, bis Sie den Cache leeren. Alternativ können Sie hook_page_attachments() verwenden, Punkte an drupalSettings.YOUR_MODULE_OR_THEME.YOUR_VARIABLE anhängen, in JavaScript darauf zugreifen und im Browser rendern.

Normalerweise wird der Cache für Seiten deaktiviert, wenn das Menü "Profil" bei der Site-Leistung angezeigt wird.

2
adal

Deaktivieren Sie den Cache für dieses Menü in hook_preprocess_menu(), indem Sie $variables['#cache']['max-age'] bis 0.

0
Roman Kuntyi