Drupal 8 - Définir un fil d'Ariane personnalisé

Gestion des fils d'ariane

Drupal 8 améliore grandement la manière de gérer le fil d'Ariane (ou breadcrumbs en Anglais). Dans ce post nous allons voir comment définir un fil d'Ariane pour les contenus d'un type particulier.

Ici nous considérerons que :

  • Le type de contenu s'appellera "Témoignage", son nom machine sera "temoignage"
  • Mon module s'apelle "temoignages_module"
  • J'ai une page de listing définie par un controller dont la route sera temoignages.page_listing.

Ces éléments seront à adapter en fonction de vos besoins.

Définitions du service

S'il n'existe pas, créer le fichier temoignages_module.services.yml et ajouter le contenu suivant :

services:
  temoignages_module.breadcrumb.temoignage:
    class: Drupal\temoignages_module\Breadcrumb\TemoignagesBreadcrumb
    tags:
      - { name: breadcrumb_builder, priority: 100 }

Implémentation du service

Toujours dans le module, créer le fichier "TemoignagesBreadcrumb.php" dans le dossier : src/Breadcrumb du module temoignages_module, et y coller le contenu suivant :

<?php

namespace Drupal\temoignages_module\Breadcrumb;

use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;
use Drupal\Core\Breadcrumb\Breadcrumb;

class TemoignagesBreadcrumb implements BreadcrumbBuilderInterface {

  public function applies(RouteMatchInterface $route_match) {
    if ($route_match->getCurrentRouteMatch()->getRouteName() == 'entity.node.canonical') {
      $node = $route_match->getParameter('node');
      if ($node->getType() == 'temoignage') {
        return TRUE;
      }
    }
    return FALSE;
  }

  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
    $breadcrumb->addCacheContexts(['route']);
    $links = [];
    $links[] = Link::createFromRoute(t('Home'), '<front>');
    $links[] = Link::createFromRoute(t('Tous les témoignages'), 'temoignages_module.page_listing');
    return $breadcrumb->setLinks($links);
  }
}

En détails

La première méthode applies doit retourner TRUE ou FALSE en fonction de si on est dans un cas ou notre breadcrumb personnalisé doit être appliqué.

Je vérifie pour commencer que je suis en train de visualiser une node :

$route_match->getCurrentRouteMatch()->getRouteName() == 'entity.node.canonical'

Si c'est le cas, je récupère cette node et si elle est bien du type "temoignage" je retourne TRUE

$node = $route_match->getParameter('node');
if ($node->getType() == 'temoignage') {
  return TRUE;
}

Sinon je retourne FALSE.

Enfin, la méthode build, comme son nom l'indique construit le fil d'Ariane, qui consiste en fait en un tableau de liens.

Je commence par mettre un tag de cache à mon fil d'Ariane en lui disant qu'il dépend de la route.

$breadcrumb->addCacheContexts(['route']);

Je construis ensuite mon tableau de liens, qui en sera constitué de deux, le premier vers la page d'accueil et le second vers ma page de listing :

$links = [];
$links[] = Link::createFromRoute(t('Home'), '<front>');
$links[] = Link::createFromRoute(t('Tous les témoignages'), 'temoignages_module.page_listing');
return $breadcrumb->setLinks($links);

Et... c'est tout, plus qu'à reconstruire le cache et vous pourrez vérifier que votre fil d'Ariane fonctionne bien.

Si vous souhaitez faire un élément du fil d'Ariane sans lien, vous pouvez utiliser le placeholder <none> :

$links[] = Link::createFromRoute(t('Mon élément sans lien'), '<none>');

Vous trouverez plus d'exemple dans les sources de mon module de pronostics : https://github.com/mespronos/mespronos/tree/8.x-1.x/src/Breadcrumb, pour la définitions des services liés, c'est ici : https://github.com/mespronos/mespronos/blob/8.x-1.x/mespronos.services….

Commentaires

Du point de vue d'un site builder c'est certes indigeste, je n'ai pas encore regardé ce qui existait en UI (genre context, breadcrumb_menu...)

Du point de vue développeur, c'est effectivement plus verbeux, mais par contre ça permettra de définir des règles plus "propres", et de ne pas se demander «Bon celui là comment il est défini ?».

bon, du moment qu'il y a des outils pour pondre ce genre de code automatiquement, je devrais y survivre.

C'est vraiment mieux que ce qui se faisait dans D7 d'un point de vue logique mais je regrette qu'ils aient pas poussé plus loin pour se rapprocher du fonctionnement de Crumbs en ne demandant pas à récupérer tout le breadcrumb d'un coup mais juste le parent de la route en cours en bouclant de parent en parent en repassant dans le breadcrumb builder. En bonus, avec un cache bien foutu, ça aurait pu être ultra rapide en plus d'être logique et souple au possible...
Ça me donne envie de contrib le futur Breadcrumb builder du core ;)

Ajouter un commentaire

Ne sera pas publié
CAPTCHA
Désolé, pour ça, mais c'est le seul moyen pour éviter le spam...