Come posso modificare il titolo di un collegamento al menu?


8

Nel mio sito Web, gli utenti possono raccogliere alcuni "punti" nel tempo. Ho un menu nella barra in alto con alcuni collegamenti (ad esempio "home", "profilo", "logout"). Voglio modificare la voce di menu "profilo" e aggiungere i punti numerici di proprietà dell'utente attualmente connesso.

Ho provato diversi hook e sono quasi riuscito a ottenere quello che volevo hook_link_alter().

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

Ho cancellato la cache (con drush cr) e la voce di menu mostra il valore che desidero. Ma, se il valore cambia per qualche motivo, mostra il vecchio valore. Devo cancellare sempre la cache per aggiornarne il valore.

Come posso evitare di pulire la cache per aggiornare il titolo del menu tutte le volte che cambiano i punti guadagnati dall'utente?


Sembra che tu abbia bisogno di plugin personalizzati per questo. Domanda interessante. Generalmente dovresti evitare di implementare tutti i ganci della vecchia scuola in D8. La domanda è come modificare il titolo del menu tramite plug-in personalizzato.
Codium,

Il tuo menu è in blocco? In tal caso, prova a impostare la cache su 0 per quel blocco
pbonnefoi,

è un blocco creato dall'interfaccia di amministrazione. Non ho avuto accesso alla configurazione della cache :)
matthieu lopez,

Ti suggerisco di iniziare con drupal.org/docs/8/api/menu-api , '#cache' => ['max-age' => 0], non è una soluzione. è necessario creare un collegamento al menu dinamico.
Arnold PÉTER,

"la voce di menu mostra il valore desiderato" Hai controllato il menu con un altro account utente? Sospetto che mostri lo stesso numero di punti per tutti gli utenti.
ya.teck

Risposte:


7

Suggerisco di implementare un plug-in di collegamento al menu personalizzato. Il codice seguente presuppone che il nome del modulo sia un esempio .

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

}

Se non si desidera iniettare il servizio di database, la classe diventerebbe molto più semplice.

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

}

Successivamente è necessario inserire la definizione del collegamento nel file example.links.menu.yml .

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

Il problema di memorizzazione nella cache

Ogni volta che il numero di punti viene modificato, la cache dei collegamenti di menu deve essere invalidata come segue.

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

Devi trovare il posto giusto per questo. Se i punti gestiti dal modulo contribuito controllano l'API del modulo e raccolgono un hook appropriato ( hook_points_insert () , hook_points_delete () e così via).

Poiché il numero di punti viene calcolato individualmente per ciascun account utente, puoi prendere in considerazione l'utilizzo di tag cache per account (qualcosa del genere ['example.points_count.' . $uid]). Pertanto, la cache verrà conservata per gli utenti con punti invariati.


Per generare il codice per il plug-in Collegamento menu ho usato Drupal Code Generator .


Questa risposta è perfetta (e più utile dell'attuale documentazione ufficiale . Tuttavia, il file yaml dovrebbe essere chiamato esempio.link.menu.yml, nessun esempio.menu-links.yml . Successivamente, svuota la cache e la tua voce di menu dovrebbe apparire
Sut3kh,

È possibile sovrascrivere anche il metodo getRouteParameters ()? Se no, come si possono modificare route_parameters in modo dinamico? Nel mio caso ho {utente} nel routing e il collegamento al menu dovrebbe fornire l'ID utente in modo dinamico come ID utente dell'utente corrente.
Igal,

@Igal pensa che sia possibile.
ya.teck

2

Ho affrontato lo stesso problema. Le voci di menu sono memorizzate nella cache, quindi mostra sempre il vecchio valore fino a quando non si cancella la cache. Un modo alternativo è usare hook_page_attachments(), collegare punti a drupalSettings.YOUR_MODULE_OR_THEME.YOUR_VARIABLE, e accedervi in ​​JavaScript e renderizzarli nel browser.

Il modo normale è disabilitare la cache per le pagine ogni volta che viene visualizzato il menu "profilo" al rendimento del sito.


0

Disabilita la cache per quel menu hook_preprocess_menu()impostando $variables['#cache']['max-age']su 0.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.