Drupal 8: How create a simple custom module for breadcrumbs: Example #2

19 Sep.2018
drupal 8 custom breadcrumbs

In the previous article "How to create a simple custom module for breadcrumbs", I wrote how to make a custom module for breadcrumbs. This article extends the code shown in the previous example. Below is an example of how you can do it yourself.

Of course, this code does not have an admin interface and is not configurable. However, as practice shows, this is enough for most and easily editable at any time.

I tried to leave the necessary comments in the code. I hope this will help anyone :-)

File
easydrupal_breadcrumb.services.yml
services:
  easydrupal_breadcrumb.breadcrumb_nodes:
    class: Drupal\easydrupal_breadcrumb\Breadcrumb\BreadcrumbNodesBuilder
    tags:
     - { name: breadcrumb_builder, priority: 100 }
  easydrupal_breadcrumb.breadcrumb_views:
    class: Drupal\easydrupal_breadcrumb\Breadcrumb\BreadcrumbViewsBuilder
    tags:
     - { name: breadcrumb_builder, priority: 100 }
File
/src/Breadcrumb/BreadcrumbNodesBuilder.php
<?php
 
namespace Drupal\easydrupal_breadcrumb\Breadcrumb;
 
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;
use Drupal\node\NodeInterface;
 
class BreadcrumbNodesBuilder implements BreadcrumbBuilderInterface {
 
  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $attributes) {
    $parameters = $attributes->getParameters()->all();
    if (isset($parameters['node']) && $parameters['node'] instanceof NodeInterface) {
      return TRUE;
    }
  }
 
  /**
   * {@inheritdoc}
   */
  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
 
    $node = \Drupal::routeMatch()->getParameter('node');
    $node_type = $node->bundle();
 
    switch ($node_type) {
 
      // If node type is "article".
      // I want to add as parent of breadcrumb my summary articles view.
      case 'article':
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
        $breadcrumb->addLink(Link::createFromRoute('News', 'entity.node.canonical', ['node' => '10360']));
 
        break;
 
      // If node type is "event"
      // I want to add as parent of breadcrumb my summary event view.
      case 'event':
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
        $breadcrumb->addLink(Link::createFromRoute('Events', 'entity.node.canonical', ['node' => '8085']));
 
        break;
 
      // If node type is "location / venue"
      // I want to add as parent of breadcrumb my Campus Map page.
      case 'location':
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
        $breadcrumb->addLink(Link::createFromRoute('Campus Map', 'entity.node.canonical', ['node' => '6']));
 
        break;
 
      // If node type is "person"
      // I want to add as parent of breadcrumb my Directory page.
      case 'person':
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
        $breadcrumb->addLink(Link::createFromRoute('Directory', 'view.a_z.page_1'));
 
        break;
      // If node type is "page"
      // I want to add custom breadcrumbs for few pages.
      case 'page':
 
        // Apply the custom breadcrumbs for News page.
        if ($node->id() == '10360') {
          $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
          $breadcrumb->addLink(Link::createFromRoute('About', 'entity.node.canonical', ['node' => '15220']));
        }
 
        break;
 
      default:
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
 
        break;
 
    }
 
    // Don't forget to add cache control,otherwise you will surprised,
    // all breadcrumb will be the same for all pages.
    // 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->id()}"]);
 
    return $breadcrumb;
  }
 
}
File
src/Breadcrumb/BreadcrumbViewsBuilder.php
<?php
 
namespace Drupal\easydrupal_breadcrumb\Breadcrumb;
 
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;
 
class BreadcrumbViewsBuilder implements BreadcrumbBuilderInterface {
 
  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $attributes) {
    $parameters = $attributes->getParameters()->all();
    // I need my breadcrumbs for a few views ONLY.
    if (isset($parameters['view_id']) && !empty($parameters['view_id'])) {
      return TRUE;
    }
  }
 
  /**
   * {@inheritdoc}
   */
  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
 
    $view_name = \Drupal::routeMatch()->getParameter('view_id');
 
    switch ($view_name) {
 
      case 'glossary':
        $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
        $breadcrumb->addLink(Link::createFromRoute('A-Z Index', '<nolink>'));
 
        break;
 
    }
 
    // Don't forget to add cache control by a route, otherwise you will surprised,
    // all breadcrumb will be the same for all pages.
    $breadcrumb->addCacheContexts(['route']);
 
    return $breadcrumb;
  }
 
}

Conclusion

I hope the information in this article helpful. And of course, I would happy if you can provide the own solution in a comment below.