Drupal 8 麵包屑爬坑紀錄

Drupal 8 麵包屑爬坑紀錄

Drupal 8 正式版到現在已經快兩年了,7 常用的模組很多都已經有 8 的版本,甚至是已經直接納入核心之內,到現在就還是沒有 Path Breadcrumbs 8 的版本,實在是讓人很頭大,所以只能尋找其他替代的模組來實做這個功能。

代替模組的選擇

稍微談論一下這幾個模組,Easy Breadcrumb 完全照著 URL 走所以可行性最高,Menu Breadcrumb 太累人了,全都要建立 Menu 所以跳過,Current Page Crumb 就幫你把 page title 掛上去而已沒啥用,Views breadcrumb 根本就沒用R~。

Easy Breadcrumb 優缺點分析

上面列出的四個模組,Easy Breadcrumb 最能讓我們方便的實作出麵包屑的功能。

優點:
* 模組參數設定很彈性
* 控制 URL 就能控制麵包屑

缺點:
* 被 URL 吃死
* 多國語言有點問題

就以上看起來,Easy Breadcrumb 確實是可以暫時代替 Path Breadcrumbs 來實作麵包屑的功能,可是你的麵包屑長這樣Home > Node > 2還是得想辦法解決。

控制 URL

說到控制 URL 想必 7 的使用者腦海裡立馬就會有可以用的模組解答出來,就是用 Pathauto 好家在有 8 的版本可以用,真是謝天謝地。
Pathauto 的教學與設定在這篇就不討論了,相信有使用過 7 的版本大家應該也很熟就是了, 8 的使用以及設定上應該也是不會有什麼大問題才對。
剛剛有提到的多國語言有點問題其實就是 Pathauto 在 token [node:content-type:name] 再產生 URL 上還是會顯示 source language,個人的解決方法就是土法煉鋼,各個語言的 pattern 設定過一遍吧。

自己寫模組

要是模組的解法你不喜歡,你覺得都必須被 URL 綁死想要自己來也是可以的,以下是我自己寫的模組 code 。

用 drupal console 產生模組挺快的,指令: drupal gm

我產生了一個自己的模組叫 my_breadcrumb

接著在我們的模組內新增一個 my_breadcrumb.services.yml 的檔案

services:
 my_breadcrumb.breadcrumb:
   class: Drupal\my_breadcrumb\Breadcrumb\MymoduleBreadcrumbBuilder
   tags:
    - { name: breadcrumb_builder, priority: 1004 }

你如果問我說 priority 為何要寫 1004 ,因為我同時有使用 Easy Breadcrumb 然而 Easy Breadcrumb 的 breadcrumb_builder priority 是 1003 所以我們的模組效果必須要在 Easy Breadcrumb 之後,不然順序會被蓋掉。

接著新增一個 src/Breadcrumb/MymoduleBreadcrumbBuilder.php 的檔案

<?php

namespace Drupal\my_breadcrumb\Breadcrumb;

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

class MymoduleBreadcrumbBuilder implements BreadcrumbBuilderInterface
{
    use StringTranslationTrait;

    /**
     * {@inheritdoc}
     */
    public function applies(RouteMatchInterface $attributes)
    {
        $parameters = $attributes->getParameters()->all();
        // 針對 views page
        if (isset($parameters['view_id'])) {
            // dpm($parameters['view_id']);
            $views_id = array('news',);
            if (in_array($parameters['view_id'], $views_id)) {
                return true;
            }
            return false;
        }
        // 針對 content type
        if (isset($parameters['node'])) {

            $type = $parameters['node']->getType();
            if ($type == 'article') {
                return true;
            }
            return false;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function build(RouteMatchInterface $route_match)
    {
        $parameters = $route_match->getParameters()->all();
        $breadcrumb = new Breadcrumb();
        $breadcrumb->addCacheContexts(["url"]);
        // 是 views page 走這裡
        if (isset($parameters['view_id'])) {
            $breadcrumb->addCacheTags(["view_id:{$parameters['view_id']}"]);
            if ($parameters['view_id'] == 'news') {
                $breadcrumb->addLink(Link::createFromRoute(t('Home'), '<front>'));
                $breadcrumb->addLink(Link::createFromRoute(t('News'), 'view.news.page_1'));
            }
        }
        // 是 content type 走這裡
        if (isset($parameters['node'])) {
            $type = $parameters['node']->getType();
            if ($type == 'article') {
                $breadcrumb->addLink(Link::createFromRoute(t('Home'), '<front>'));
                $breadcrumb->addLink(Link::createFromRoute(t('Article'), 'view.news.page_1'));
                $breadcrumb->addLink(Link::createFromRoute($parameters['node']->getTitle(), '<none>'));
            }
        }


        return $breadcrumb;
    }
}

$breadcrumb->addLink(Link::createFromRoute(t('News'), 'view.news.page_1')); Route 要寫 view.news.page_1 Drupal 才會認識,你如果寫 /news 會跟你說找不到這個 Route

整個模組的檔案架構如下圖:

兩者的效果

Easy Breadcrumb 搭配 Pathauto


custom module 的效果


結論

不管是模組還是 custom module 兩者上的效果都沒有什麼不同,只是 custom module 自己寫彈性當然最大啦,如果對寫 code 不熟悉的話也是可以使用 Easy Breadcrumb 的。
只是還是要抱怨一下,都過了這麼久了為什麼 Path Breadcrumbs 還是沒有出 8 的版本啊!
希望以上這些可以幫助到曾經被麵包屑坑過的人。

參考資料

How to Create Breadcrumb in Drupal 8
Drupal 8 How to do a custom taxonomy breadcrumb?
How do you implement a breadcrumb?