Skip to content

Instantly share code, notes, and snippets.

@jonpugh
Created May 5, 2016 00:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jonpugh/ccaeb01e173abbc6c88f7a332d271e4a to your computer and use it in GitHub Desktop.
Save jonpugh/ccaeb01e173abbc6c88f7a332d271e4a to your computer and use it in GitHub Desktop.
Add Taxonomy Term to a Node's Breadcrumb in Drupal 8
<?php
// src/Breadcrumbs.php
namespace Drupal\modulename;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;
/**
* Class Breadcrumbs.
*
* @package Drupal\modulename
*/
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_section", and that field has data,
// Add that term as a breadcrumb link.
if (!empty($node->field_section->entity)) {
$breadcrumb->addLink($node->field_section->entity->toLink());
}
return $breadcrumb;
}
}
# modulename.services.yml
services:
modulename.breadcrumbs:
class: Drupal\modulename\Breadcrumbs
tags:
- { name: breadcrumb_builder, priority: 100 }
@mfrosch
Copy link

mfrosch commented Jun 19, 2017

If you also want the parents you can replace

    if (!empty($node->field_section->entity)) {
      $breadcrumb->addLink($node->field_section->entity->toLink());
    }

with

    if (!empty($node->field_section->entity)) {
      $term = $node->field_section->entity;
      $storage = \Drupal::service('entity_type.manager')
        ->getStorage('taxonomy_term');
      $parents = $storage->loadParents($term->id());

      if (!empty($parents)) {
        foreach ($parents as $index => $parent) {
          $breadcrumb->addLink($parent->toLink());
        }
      }

      $breadcrumb->addLink($term->toLink());
    }

@int-ua
Copy link

int-ua commented Dec 3, 2020

Thank you all, here is a slightly more parametrized theme code version for non-node entities with taxonomy parents:

/**
 * Implements hook_system_breadcrumb_alter().
 */
function THEMENAME_preprocess_breadcrumb(array &$vars) {
  // proper taxonomy breadcrumbs for Commerce Products through field_category
  $entity_type = 'commerce_product'; // TODO: change or verify
  $taxonomy_field_name = 'field_category'; // TODO: change or verify

  if (($entity = \Drupal::routeMatch()->getParameter($entity_type)) && $vars['breadcrumb']) {
    $cache_tag = "{$entity_type}:{$entity->product_id->value}"; // TODO: change or verify

    $breadcrumb = &$vars['breadcrumb'];
    if (!empty($entity->$taxonomy_field_name->entity)) {
      $node_url = array_pop($breadcrumb);

      $term = $entity->$taxonomy_field_name->entity;
      $storage = \Drupal::service('entity_type.manager')
        ->getStorage('taxonomy_term');
      $parents = $storage->loadParents($term->id());
      if (!empty($parents)) {
        foreach ($parents as $index => $parent) {
          array_push($breadcrumb, $parent->toLink());
        }
      }
      array_push($breadcrumb, $term->toLink());

      array_push($breadcrumb, $node_url);

      // Implementing Cache.
      $vars['#cache']['contexts'][] = "url.path";
      $vars['#cache']['tags'][] = $cache_tag;
    }
  }
}

@bohotina
Copy link

bohotina commented Feb 6, 2021

If you also want the parents you can replace

    if (!empty($node->field_section->entity)) {
      $breadcrumb->addLink($node->field_section->entity->toLink());
    }

with

    if (!empty($node->field_section->entity)) {
      $term = $node->field_section->entity;
      $storage = \Drupal::service('entity_type.manager')
        ->getStorage('taxonomy_term');
      $parents = $storage->loadParents($term->id());

      if (!empty($parents)) {
        foreach ($parents as $index => $parent) {
          $breadcrumb->addLink($parent->toLink());
        }
      }

      $breadcrumb->addLink($term->toLink());
    }

How would can I implement this solution to show the parents but using the YOURTHEME.theme preprocess function instead of the module? Thank you in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment