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?