In this tutorial we will go through how to create Drupal custom breadcrumb. In Drupal 7 we were using drupal_set_breadcrumb to get breadcrumb as pre requirement, but in Drupal 8 breadcrumb -  drupal_set_breadcrumb() is removed and breadcrumb is added as service. Let us learn, how to create breadcrumbs as a Drupal 8 service.


In Drupal 8, breadcrumb service is introduced as new concept to decouple reusable functionality. Also to make these services pluggable and replaceable by registering them with a Drupal 8 service container. For a developer, services are used to perform operations like accessing the database or sending an e-mail.

Let's try it now!

Let's add our own new builder which will make all "article" node, appear as breadcrumb children of a View. We need to implement the BreadcrumbBuilderInterface, We'll add a class to our module like the one mentioned below:

namespace Drupal\mymodule\Breadcrumb;

use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;

class MymoduleBreadcrumbBuilder implements BreadcrumbBuilderInterface{
   /**
    * {@inheritdoc}
    */
   public function applies(RouteMatchInterface $attributes) {
       $parameters = $attributes->getParameters()->all();
       if (!empty($parameters['node'])) {
           return $parameters['node']->getType() == 'article';
       }
   }

   /**
    * {@inheritdoc}
    */
   public function build(RouteMatchInterface $route_match) {
       $breadcrumb = new Breadcrumb();
       $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));
       $breadcrumb->addLink(Link::createFromRoute('Article', '<<<your route for article>>>
'));
       return $breadcrumb;
   }

}

Two methods, that's it!

In the applies() method, we are passing an object of RouteMatchInterface about the current request. In our case, we know that this builder only cares about showing the node page specifically of type "article". So we return TRUE if that's the case, indicating that our build() method should be called, or FALSE to say "ignore me!"


In build() method, we can build the breadcrumb array however we feel like. In this case we're just going to hard code a few links but we can use any logic , knowing that  only our code will be in control of the breadcrumb on this request.

A few important things to note:

  • $parameters = $attributes->getParameters()->all()

In $parameters we can get the available parameters for the current page.
Eg. : For view page will get ‘view_id’ and ‘display_id’

  • Similarly for node page we will get ‘node’

So in our case we have to create breadcrumb for node page of type ‘article’
Here we are checking  $parameters['node']->getType() which is of type article,  hence it will return TRUE.

  • In the build() method we need to return an object of Breadcrumb class.

$breadcrumb = new Breadcrumb();

Creating an object of Breadcrumb Class.

$breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));

In adding link to the breadcrumb class object, we need to pass object of Link class for creating a link.


Now we need to brief the  system about our class. To do so, we have to define a new Drupal 8 service referring to our new class. We will do the same  in our mymodule.services.yml file


#mymodule.services.yml
services:
 mymodule.breadcrumb:
   class: Drupal\mymodule\Breadcrumb\MymoduleBreadcrumbBuilder
   tags:
    - { name: breadcrumb_builder, priority: 100 }

Similar to an "info hook" in Drupal 7, here we're defining a service named mymodule.breadcrumb. It will be an instance of breadcrumb class. If required we can pass argument to our class constructor. It should be noted that in this case  we also tag the service.


Tagged Drupal 8 services are features of Symfony DependencyInjection component specifically which will  tell the system to automatically connect our builder to the breadcrumb manager. The priority here specifies in what order various builder will be called,in this case the higher as first. If it’s more than one then applies() method  will return true. In that case the builder with higher priority will be used and the rest will be ignored.


That's it!


One simple class, a few lines of YAML, and we've spotted our new breadcrumb rule into the system.There's no more mystery about who called drupal_set_breadcrumb(), when it was called and who overrode whom. It’s all clear and predictable if you look at the priorities.
All the breadcrumb logic is in classes which are easily unit testable with PHPUnit.


Finally, since everything is a service, it is possible for a site-specific module to completely disable other modules' breadcrumb logic without hacking them. We have finally understood, how to create breadcrumb. 
.


Project url: https://www.drupal.org/project/views_breadcrumb

 

comments powered by Disqus