Drupal - How can I add Taxonomy Term to a Node's Breadcrumb?

Themers who don't want to use a custom module to implement a BreadcrumbBuilder can change the breadcrumbs in a preprocess hook.

Example how you can add a link before the last link:

function mytheme_preprocess_breadcrumb(&$variables) {
  $breadcrumb = &$variables['breadcrumb'];
  $lastlink = array_pop($breadcrumb);
  array_push($breadcrumb, [
    'text' => 'New Link',
    'url' => '/newlink',
  ]);
  array_push($breadcrumb, $lastlink);
}

If you add a taxonomoy term from a node you would have to add both as cache tags and a cache context on the url to make this work.


We can implement custom breadcrumb either via module or via HOOK_preprocess_breadcrumb.

Via HOOK_preprocess_breadcrumb:

Add this in your YOURTHEME.theme

/**
 * Implements HOOK_preprocess_breadcrumb().
 */
function YOURTHEME_preprocess_breadcrumb(&$variables) {
  if (($node = \Drupal::routeMatch()->getParameter('node')) && $variables['breadcrumb']) {
    $breadcrumb = &$variables['breadcrumb'];
    if (!empty($node->field_tags->entity)) {
      $term_url = $node->field_tags->entity->toLink();
      $node_url = array_pop($breadcrumb);
      array_push($breadcrumb, $term_url);
      array_push($breadcrumb, $node_url);
      // Implementing Cache.
      $variables['#cache']['contexts'][] = "url.path";
      $variables['#cache']['tags'][] = "node:{$node->nid->value}";
    }
  }
}

Via module:

In custom_breadcrumb.module file

<?php

namespace Drupal\custom_breadcrumb;

use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;

/**
 * Class Breadcrumbs.
 *
 * @package Drupal\custom_breadcrumb
 */
class Breadcrumbs implements BreadcrumbBuilderInterface {
  use StringTranslationTrait;

  /**
   * {@inheritDoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    return $route_match->getRouteName() == 'entity.node.canonical' && $route_match->getParameter('node') instanceof NodeInterface;
  }

  /**
   * {@inheritDoc}
   */
  public function build(RouteMatchInterface $route_match) {
    $node = $route_match->getParameter('node');
    $breadcrumb = new Breadcrumb();

    // By setting a "cache context" to the "url", each requested URL gets it's
    // own cache. This way a single breadcrumb isn't cached for all pages on the
    // site.
    $breadcrumb->addCacheContexts(["url"]);

    // By adding "cache tags" for this specific node, the cache is invalidated
    // when the node is edited.
    $breadcrumb->addCacheTags(["node:{$node->nid->value}"]);

    // Add "Home" breadcrumb link.
    $breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '<front>'));

    // Given we have a taxonomy term reference field named "field_tags" and that
    // field has data, add that term as a breadcrumb link.
    if (!empty($node->field_tags->entity)) {
      $breadcrumb->addLink($node->field_tags->entity->toLink());
    }
    return $breadcrumb;
  }

}

and then in custom_breadcrumb.services.yml

services:
  custom_breadcrumb.breadcrumbs:
    class: Drupal\custom_breadcrumb\Breadcrumbs
    tags:
      - { name: breadcrumb_builder, priority: 100 }

Both the ways are achievable, if your question is which one should be followed and which one should be referred as a best practice, refer https://drupal.stackexchange.com/a/238962/3808

Tags:

Breadcrumbs

8