Drupal 8 Two ways to customise Breadcrumb

Profile picture for user a.berramou
Azz-eddine BERRAMOU 25 November, 2019

To customise Breadcrumb there is two ways to achieve this:

Let's assume that you have a breadcrumb Home > Article Title and you want to customized it to be for instance Home > Tag > Article Title

  • First option oriented object way.

   First step Create class let's called it ArticleBreadcrumbBuilder should be located in YourModule/src/Breadcrumb folder.

<?php

namespace Drupal\YourModule\Breadcrumb;

use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Link;
use Drupal\taxonomy\Entity\Term;

class ArticleBreadcrumbBuilder implements BreadcrumbBuilderInterface {

  public function applies(RouteMatchInterface $route_match) {
    $parameters = $route_match->getParameters()->all();
    if (isset($parameters['node'])) {
      return $parameters['node']->getType() === 'article';
    }
    if (isset($parameters['term'])) {
      return TRUE;
    }
  }

  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
    $node = \Drupal::request()->attributes->get('node');
    $term_id = $node->field_tags->getValue()[0]['target_id'];
    $term = Term::load($term_id);
    $breadcrumb->addCacheContexts(["url"]);
    $breadcrumb->addLink(Link::createFromRoute(t('Home'), '<front>'));
    $breadcrumb->addLink(Link::createFromRoute(t('Articles'), '<none>'));
    $breadcrumb->addLink(Link::createFromRoute(
$term->getName(), 'entity.taxonomy_term.canonical', ['taxonomy_term' => $term->id()]
));

    $request = \Drupal::request();
    $route_match = \Drupal::routeMatch();
    $page_title = \Drupal::service('title_resolver')
      ->getTitle($request, $route_match->getRouteObject());
    if (!empty($page_title)) {
      $breadcrumb->addLink(Link::createFromRoute($page_title, '<none>'));
    }

    return $breadcrumb;
  }
}

 But we didn't finish yet, let's tell Drupal consider this class as Breadcrumb handler, so we should inject it as service:

Create YouModule.services.yml :

services:
  YourModule.breadcrumb:
    # The namespace + classname from your BreadcrumbBuilderInterface class
    class: Drupal\YourModule\Breadcrumb\ArticleBreadcrumbBuilder
    # Priority determines the order in which Breadcrumb services run.
    tags:
      - { name: breadcrumb_builder, priority: 100 }
<?php 

use Drupal\taxonomy\Entity\Term;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Implements hook_system_breadcrumb_alter().
 */
function YourModule_system_breadcrumb_alter(Breadcrumb &$breadcrumb, RouteMatchInterface $route_match, array $context) {
  // dpm($route_match);
  $node = \Drupal::request()->attributes->get('node');
  if ($node && $node instanceof Drupal\node\Entity\Node) {
    if ($node->bundle() == 'article') {
      // Add Articles item.
      $breadcrumb->addLink(Link::createFromRoute(t('Articles'), '<none>'));
      // Add category term item to breadcrumb.
      // Change here the field_tags with your taxonomy you want to add to breadcrumb.
      $term_id = $node->field_tags->getValue()[0]['target_id'];
      $term = Term::load($term_id);
      $breadcrumb->addLink(
       Link::createFromRoute($term->getName(), 'entity.taxonomy_term.canonical', ['taxonomy_term' => $term->id()])
      );
      // Add title as breadcrumb item.
      $request = \Drupal::request();
      $route_match = \Drupal::routeMatch();
      $page_title = \Drupal::service('title_resolver')
        ->getTitle($request, $route_match->getRouteObject());
      if (!empty($page_title)) {
        $breadcrumb->addLink(Link::createFromRoute($page_title, '<none>'));
      }
    }
  }
}

 

And that's it, you can now alter your breadcrambs as you need!