132. 面包屑路径
“面包屑Breadcrumbs”来自格林童话故事“糖果屋”:邪恶的继母欲将汉赛尔和格莱特带到森林中丢弃,可怜的兄妹俩在沿途走过的地方偷偷撒下了面包屑,希望让这些面包屑帮助他们找到回家的路。
因此面包屑导航的作用是告诉访问者他们当前在网站中的位置以及如何返回,通常位于主导航菜单的下方,是由从顶层链接到当前链接构成的链接字符串,如:“首页>>管理>>结构>>内容类型>>文章”。
面包屑块:
在Drupal中面包屑导航是由面包屑块提供的,如下所示:
块插件id:system_breadcrumb_block
类:Drupal\system\Plugin\Block\SystemBreadcrumbBlock
需要显示面包屑路径的页面放置该块即可,该插件很简单,核心工作由面包屑管理器完成
面包屑管理器:
用于通过当前路由匹配器计算并返回当前页面的面包屑路径渲染数组,定义如下:
服务id:breadcrumb
类:Drupal\Core\Breadcrumb\BreadcrumbManager
接口:\Drupal\Core\Breadcrumb\ChainBreadcrumbBuilderInterface
使用方式:
$breadcrumbManager =\Drupal::service('breadcrumb');
$routeMatch=\Drupal::routeMatch();
$breadcrumbRenderArray=$breadcrumbManager->build($routeMatch)->toRenderable();
该管理器本身并不做实际工作,仅在容器编译阶段收集面包屑构建器,在运行时按优先级调用构建器,由构建器来生成面包屑路径
面包屑构建器:
用于实际计算面包屑渲染数组,须实现以下接口:
\Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface
仅有两个方法:
public function applies(RouteMatchInterface $route_match);
返回布尔值,用于判断该构建器是否适用于给出的路由,true为适用
public function build(RouteMatchInterface $route_match);
进行面包屑构建,如果applies方法判断可适用,则该方法就必须进行构建,返回面包屑对象:
\Drupal\Core\Breadcrumb\Breadcrumb
该对象见下文。
各模块提供了多个面包屑构建器,面包屑管理器按优先级依次调用他们,如果适用则处理,否则让优先级更低的构建器继续处理,一旦优先级高的构建器表明适用后,低优先级的构建器就不会再被调用,如果都不适用,则最后由系统模块提供的默认构建器兜底(该构建器对任意路由返回适用,见下文),默认的有如下构建器,服务id是:
taxonomy_term.breadcrumb:优先级1002
comment.breadcrumb:优先级100
system.breadcrumb.default:优先级0
面包屑对象:
用来表示一个面包屑路径,由构建器的($builder->build($route_match))方法返回,类如下:
\Drupal\Core\Breadcrumb\Breadcrumb
在程序上构建器应使用该对象提供的方法进行构建,其提供了以下主要方法:
public function setLinks(array $links)
面包屑路径是由被排序的链接构成的字符串,排序顺序通常是从顶层链接到当前链接,该方法一次性设置所有链接,由排好序的链接对象数组做参数,数组中每个元素是一个链接对象(\Drupal\Core\Link),第一个元素是顶层链接,注:一旦对象包含链接数据,则不可再调用该方法,否则抛出异常
public function addLink(Link $link)
向面包屑中添加路径链接,参数为链接对象(\Drupal\Core\Link)
public function toRenderable()
返回面包屑路径的渲染数组,默认采用主题钩子“breadcrumb”,模板为:
core/themes/classy/templates/navigation/breadcrumb.html.twig
模板预处理函数为:template_preprocess_breadcrumb(&$variables)
面包屑修改钩子:
在面包屑管理器中,当构建完面包屑路径后会派发以下修改钩子:
“system_breadcrumb”
钩子函数如:
function hook_system_breadcrumb_alter(&$breadcrumb, RouteMatchInterface $route_match, array $context)
第一个参数为前文的面包屑对象,第二个参数为路由匹配器,最后一个为上下文数组,其仅有一个键“builder”,其值为面包屑构建器对象
默认面包屑构建器:
由系统模块提供,适用于所有路由,定义如下:
服务id:system.breadcrumb.default
类:Drupal\system\PathBasedBreadcrumbBuilder
该构建器原理是按当前页面的URL路径自动判断面包屑路径,让面包屑链接的层次结构与路径的继承结构对应起来,链接文本为路径对应页面的标题,举个例子,假设路径:
“/a”
在系统中存在对应页面,其页面标题为“one”,那么她的面包屑路径就是“首页>>”,注意自己的标题并不用在自己的面包屑路径中,而是用在其子路径的面包屑中,换句话说如果此时存在路径:
“/a/b”
由于该路径 “继承”了上面的路径“/a”,所以她的面包屑路径就是“首页 >> one >>”,以此类推,如果“/a/b”的页面标题是“two”,那么路径“/a/b/c”的面包屑路径就是“首页 >> one >> two >>”
这就是基于路径信息的面包屑路径,使用中需要注意几个问题:
1、解析时,依次从当前路径解析到根路径,其中:首页内部路径、不存在对应页面的路径、和“/user”会被整体跳过
2、首页不会有面包屑路径
3、没有访问权限的链接不会出现在面包屑路径中
4、路径如果是一个别名,那么并不会转化为内部路径后再分段解析,这允许别名路径继承
5、当前页面的标题并不会出现在面包屑链接中
6、在解析面包屑链接文本时,如果对应页面没有标题,那么将使用路径中对应的“段component”代替
自定义面包屑构建器:
如果我们不想使用系统默认的基于路径继承的面包屑路径,那么只需实现一个自定义的面包屑构建器即可,在其中可以使用任意逻辑去构建面包屑,自定义操作如下:
先定义一个实现以下接口的类:
\Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface
然后将其定义为服务,并给出服务标签“breadcrumb_builder”,以及优先级即可
可参考分类术语的面包屑构建器定义:
taxonomy_term.breadcrumb:
class: Drupal\taxonomy\TermBreadcrumbBuilder
arguments: ['@entity_type.manager', '@entity.repository']
tags:
- { name: breadcrumb_builder, priority: 1002 }
注意:优先级必须大于0才起作用,因为系统默认构建器的优先级为0,该构建器适用于任意路由,因此会阻断更低优先级的所有构建器的执行,优先级设置越大越有权决定面包屑路径是否由自己处理