kgaut.net // Développeur web PHP / Drupal freelance
contactez-moi

Drupal - Les « menu deriver » pour générer des éléments de menu dynamiquement

Dans Drupal, les éléments de menu sont gérés soit via l'interface d'administration soit dans les fichiers mon_module.links.menu.yml, de la manière suivante : 

Un lien vers un noeud : 

enfarandole.main.help:
  title: 'Nous aider'
  weight: 2
  route_name: entity.node.canonical
  route_parameters:
    node: 5
  menu_name: main

Un lien vers une vue :

amicale.main.events:
  title: 'Évènements'
  weight: 1
  route_name: view.evenements.listing
  menu_name: main

Mais il est aussi possible d'utiliser un deriver, pour créer des éléments de menu de manière dynamique, dans l'exemple suivant je vais lister dans un sous menu tous les contenus d'un certains type, je commence par la déclaration de mon menu parent et de mon deriver, toujours dans le fichier mon_module.links.menu.yml :

# Mon élément parent, sans lien, qui sera dans le menu principal
amicale.main.sections:
  title: 'Sections'
  weight: 1
  route_name: '<nolink>'
  menu_name: main

# La définition de mon dériver pointant vers une classe
amicale.main.sections.section: 
  deriver: '\Drupal\mon_module\Plugin\Derivative\SectionMenuLinkDeriver'
  class: '\Drupal\Core\Menu\MenuLinkDefault'

La classe de mon dériver (web/modules/mon_module/src/Plugin/Derivative/SectionMenuLinkDeriver.php)

<?php

namespace Drupal\mon_module\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Menu deriver for content type « page_de_section ».
 */
final class SectionMenuLinkDeriver extends DeriverBase implements ContainerDeriverInterface {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected EntityTypeManager $entityTypeManager;

  /**
   * CategoryMenuLinkDeriver constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
   *   The entity type manager.
   */
  public function __construct(EntityTypeManager $entityTypeManager) {
    $this->entityTypeManager = $entityTypeManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, $base_plugin_id) {
    return new static($container->get('entity_type.manager'));
  }

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {
    $links = [];

    $storage = $this->entityTypeManager->getStorage('node');

    $query = $storage->getQuery();
    // Je charge tous les noeud du type « page_de_section »
    $query->accessCheck(TRUE);
    $query->condition('type', 'page_de_section');
    $query->sort('title');
    $sections = $query->execute();

    // Et pour chaque, je vais créer un élément de menu
    foreach ($sections as $section) {
      if (!$section = $storage->load($section)) {
        continue;
      }

      // Create menu ID.
      $menuId = 'amicale.main.sections.section:' . $section->id();

      $link = [
        'id' => $menuId,
        'route_name' => entity.node.canonical,
        'route_parameters' => ['node' => $section->id()],
        'title' => $section->label(), // Le titre de mon élément de menu (ici le titre du noeud)
        'parent' => 'amicale.main.sections', // je définis ici le menu item parent, si omis, ça sera un élément de menu de niveau 1
      ] + $base_plugin_definition;
      
      $links[$menuId] = $link;
    }

    return $links;
  }

}

On vide son cache, et voila !

Évidement tout est possible au niveau de ce que l'on veut ajouter comme élément de menu, catégories basée sur un vocabulaire, liste de membres...

 

 

Contenus en rapport

snippet · 20 Sep 2017 Drupal 8 - Définir l'item de menu actif en fonction du type de noeud snippet · 12 Mar 2018 Drupal 8 & Drupal 9 - Menu - Ajouter un élément de menu avec des paramètres GET snippet · 28 Oct 2019 Drupal 8 - Menu - Ajouter une classe à un élément de menu snippet · 2 Mar 2021 Drupal 8 & Drupal 9 - Créer des éléments de menu dans le code snippet · 20 Sep 2018 Drupal 8 - Afficher un menu dans le code

Commentaires (0)