Node with multiple taxonomies - can I pass value as URL param

Created on 28 February 2024, 9 months ago
Updated 14 June 2024, 5 months ago

Is it possible to influence which taxonomy term is referenced to construct the breadcrumb within a node?

I have a Node with multiple taxonomy references - and would like to show different breadcrumbs.

πŸ“Œ Task
Status

Active

Version

2.0

Component

Documentation

Created by

πŸ‡¬πŸ‡§United Kingdom newaytech

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @newaytech
  • πŸ‡ΊπŸ‡ΈUnited States Greg Boggs Portland Oregon

    You can implement hook_breadcrumb_alter to modify with custom code here's an example from a contrib module:

    https://git.drupalcode.org/project/dynamic_breadcrumb/-/blob/master/dyna...

    You can also try the substitute feature. In general, the breadcrumb matches the path. There is a setting to display taxonomy added to crumbs, I just don't know how it chooses which one to use when there are multiple.

  • πŸ‡¬πŸ‡§United Kingdom newaytech

    Hey Greg, thanks for the tip around the custom code. I ended up using the new BreadcrumbBuilderInterface approach - and pulling the taxonomy ID either from the URL - or the first entry in the list of taxonomies I have on the product. Works a treat - thanks for the hint!

  • πŸ‡ΊπŸ‡ΈUnited States Greg Boggs Portland Oregon

    Awesome! If you can, it would be awesome if you could post your alter hook as an example for future folks before we close this.

    ~G

  • πŸ‡ΊπŸ‡ΈUnited States Greg Boggs Portland Oregon

    I can add it to the documentation.

  • πŸ‡¬πŸ‡§United Kingdom newaytech

    Entry in services.yml

      neway_lintels.breadcrumb:
        class: Drupal\neway_lintels\BreadcrumbBuilder
        arguments: [ '@entity_type.manager', '@entity.repository' ]
        tags:
          - { name: breadcrumb_builder, priority: 1004 }
    <?php
    namespace Drupal\neway_lintels;
    
    use Drupal;
    use Drupal\commerce_product\Entity\Product;
    use Drupal\Core\Breadcrumb\Breadcrumb;
    use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
    use Drupal\Core\Entity\EntityRepositoryInterface;
    use Drupal\Core\Entity\EntityTypeManagerInterface;
    use Drupal\Core\Link;
    use Drupal\Core\Routing\LinkGeneratorTrait;
    use Drupal\Core\Routing\RouteMatchInterface;
    use Drupal\Core\StringTranslation\StringTranslationTrait;
    
    class BreadcrumbBuilder implements BreadcrumbBuilderInterface {
    
      use StringTranslationTrait;
    
      public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository) {
    
        $this->entityTypeManager = $entity_type_manager;
        $this->entityRepository = $entity_repository;
    
      }
    
      /**
       * By advent of there being a breadcrumb_builder name in the services.yml file - the Symphony framework runs
       * the below - to see if it is applicable - if it is - the bigger weight wins
       * 
       * Code by Wayne Foster, Neway Technology Ltd, UK
       * 
       * {@inheritdoc}
       */
      public function applies(RouteMatchInterface $route_match): bool {
        $allowedRoutes = [
          "entity.commerce_product.canonical",
        ];
        $routeName = $route_match->getRouteName();
        //dump("bread applies termID: " . $termID . ", routeName:" . $routeName);
        return (in_array($routeName, $allowedRoutes));
      }
    
      /**
       * {@inheritdoc}
       */
      public function build(RouteMatchInterface $route_match): Breadcrumb {
        $breadcrumb = new Breadcrumb();
        /** @var Product $entityProduct */
        $entityProduct = $route_match->getParameter('commerce_product');
        $termID = Drupal::request()->get('term');
        /** @var \Drupal\taxonomy\TermStorageInterface $parents */
        $parents;
    
        // We have found a term ID on the URL - use it
        if ($termID && $termID > 0) {
          $parents = $this->entityTypeManager->getStorage('taxonomy_term')
            ->loadAllParents($termID);
        } // if not - then get the first entry on the product category list of taxonomies
        else {
          $taxonomy_field_name = 'product_category';
          /** @var  \Drupal\taxonomy\Entity\Term $productCategory */
          $productCategory = $entityProduct->$taxonomy_field_name->entity;
          //dump("firstCategory", $productCategory);
          $parents = $this->entityTypeManager->getStorage('taxonomy_term')
            ->loadAllParents($productCategory->id());
        }
    
        // Add a home page link to the start of the breadcrumb render array
        $links[] = Link::createFromRoute(t("Home"), '<front>');
        $linksTax = [];
        // iterate up the taxonomy parents
        foreach ($parents as $parent) {
          $parent = $this->entityRepository->getTranslationFromContext($parent);
          $linksTax[] = $parent->toLink();
        }
        $links = array_merge($links, array_reverse($linksTax));
        $links[] = Link::createFromRoute($entityProduct->getTitle(), '<none>');
        $breadcrumb->setLinks($links);
        $breadcrumb->addCacheContexts(['route', 'url.path','url.query_args']);
    
        return $breadcrumb;
      }
    
    }
    
  • πŸ‡ΊπŸ‡ΈUnited States Greg Boggs Portland Oregon

    Interesting approach to run a new builder restricted only for a certain path to selectively apply options. If you had used the taxonomy option in Easy Breadcrumb, it would apply to every route on the site instead of selectively to your commerce products. Super cool.

  • πŸ‡©πŸ‡ͺGermany spuky

    Might be worth to turn this into a Documentation Page

Production build 0.71.5 2024