Bagaimana cara mengubah judul tautan menu?

8

Di situs web saya, pengguna dapat mengumpulkan beberapa 'poin' dari waktu ke waktu. Saya memiliki menu bilah atas dengan beberapa tautan (mis. "Rumah", "profil", "logout"). Saya ingin mengubah item menu "profil" dan menambahkan poin nomor yang dimiliki oleh pengguna yang terhubung saat ini.

Saya mencoba beberapa kail, dan saya hampir berhasil mendapatkan apa yang saya inginkan hook_link_alter().

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

Saya menghapus cache (dengan drush cr), dan item menu menunjukkan nilai yang saya inginkan. Tetapi, jika nilainya berubah karena suatu alasan, itu menunjukkan nilai yang lama. Saya harus menghapus cache setiap saat untuk memperbarui nilainya.

Bagaimana saya bisa menghindari pembersihan cache untuk memperbarui judul menu setiap kali poin yang diperoleh dari pengguna berubah?

matthieu lopez
sumber
Sepertinya Anda memerlukan plugin khusus untuk ini. Pertanyaan menarik. Umumnya Anda harus menghindari penerapan kait sekolah lama di D8. Pertanyaannya adalah bagaimana mengubah judul menu melalui plugin khusus.
Codium
Apakah menu Anda di blok? Jika itu masalahnya, cobalah untuk mengatur cache ke 0 untuk blok itu
pbonnefoi
itu adalah blok yang dibuat dari antarmuka administrasi. Saya tidak mengakses konfigurasi cache :)
matthieu lopez
Saya sarankan Anda mulai dengan drupal.org/docs/8/api/menu-api , '#cache' => ['max-age' => 0], bukan solusi. Anda perlu membuat tautan menu dinamis.
Arnold PÉTER
"item menu menunjukkan nilai yang saya inginkan" Apakah Anda sudah memeriksa menu dengan akun pengguna lain? Saya menduga itu menunjukkan jumlah poin yang sama untuk semua pengguna.
ya. Cek

Jawaban:

7

Saya sarankan menerapkan plugin tautan menu kustom. Kode di bawah ini mengasumsikan nama modul Anda adalah contoh .

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

}

Jika Anda tidak ingin menyuntikkan layanan basis data, kelas akan menjadi lebih sederhana.

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

}

Selanjutnya Anda perlu memasukkan definisi tautan ke file example.links.menu.yml .

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

Masalah caching

Setiap kali jumlah poin diubah, cache tautan menu harus tidak valid sebagai berikut.

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

Anda perlu mencari tempat yang tepat untuk ini. Jika poin dikelola oleh modul yang disumbang, periksa API modul dan ambil kait yang sesuai ( hook_points_insert () , hook_points_delete () dan sebagainya).

Karena jumlah poin dihitung untuk setiap akun pengguna secara individual, Anda dapat mempertimbangkan untuk menggunakan tag cache setiap akun (sekitar ['example.points_count.' . $uid]). Karenanya cache akan disimpan untuk pengguna dengan poin yang tidak berubah.


Untuk menghasilkan kode untuk plugin tautan Menu, saya menggunakan Drupal Code Generator .

ya.teck
sumber
Jawaban ini tepat (dan lebih bermanfaat daripada dokumentasi resmi saat ini . Namun, file yaml harus dinamai example.links.menu.yml, no example.menu-links.yml . Setelah itu, kosongkan cache dan item menu Anda akan muncul
Sut3kh
Apakah ini mungkin untuk menimpa juga metode getRouteParameters ()? Jika tidak, bagaimana cara mengubah route_parameters menjadi dinamis? Dalam kasus saya, saya memiliki {user} dalam perutean dan tautan menu harus memberikan ID pengguna secara dinamis sebagai ID pengguna pengguna saat ini.
Igal
@Igal pikir itu mungkin.
ya.teck
2

Saya menghadapi masalah yang sama. Item menu di-cache, sehingga selalu menampilkan nilai lama sampai Anda menghapus cache. Cara alternatif adalah menggunakan hook_page_attachments(), lampirkan poin ke drupalSettings.YOUR_MODULE_OR_THEME.YOUR_VARIABLE, dan akses di JavaScript, dan render di browser.

Cara normal adalah menonaktifkan cache untuk halaman setiap kali menu "profil" ditampilkan pada kinerja situs.

adal
sumber
0

Nonaktifkan cache untuk menu itu hook_preprocess_menu()dengan mengatur $variables['#cache']['max-age']ke 0.

Roman Kuntyi
sumber