110. 菜单本地动作MenuLocalActions
菜单本地动作Menu local actions用来为目标路由提供操作动作,在路由对应页面中以操作按钮呈现,比如在呈现某内容列表的路由页面提供一个添加新内容的按钮,可参考内容管理页(/admin/content)的“添加内容”按钮
本地动作块:
路由页面是以本地动作块来呈现本地动作按钮的,因此需显示本地动作的页面须添加该块,块定义如下:
块管理标签admin_label:Primary admin actions
块插件ID:local_actions_block
块插件类:Drupal\Core\Menu\Plugin\Block\LocalActionsBlock
该块是一个很简单的块(见本系列块相关主题),主要渲染工作由菜单本地动作插件管理器完成(见下)。
本地动作概述:
系统将动作按钮视为插件,一个按钮对应一个插件定义,一对一关系,如果需要为某页面添加动作按钮,定义插件即可,具体是在模块根目录下建立文件:“模块名.links.action.yml”,其中以根键做插件id,其值做插件定义,插件定义有如下键名:
route_name:动作按钮所指页面的路由名,换句话说即点击后跳转到该路由,字符串值,必填项
route_parameters:对应以上路由名的路由参数,数组值,默认为空数组[],可选
title:动作按钮文本,字符串值,被系统理解为可翻译的,在系统内部被转化为翻译对象TranslatableMarkup,用于按钮上显示的文本,并非title属性值
title_context:可选,标题翻译上下文,见翻译系统
appears_on:路由名构成的数组,指示该本地动作将出现在哪些路由页面中
weight:排序权重,默认为null
options:按钮链接选项,见本系列URL篇,可在其中指定链接属性,如是否在新窗口打开、属性值等
id:插件id,系统以yml文件中的定义根键自动赋值,最佳实践推荐根键采用路由名,如果多个定义有相同路由名,那么可以采用后缀加以区分
provider:提供插件定义的模块名,由系统赋值
deriver:插件派生器的全限定类名,见插件系统
cache_tags:数组值,缓存标签,默认为空数组(见默认插件类)
cache_contexts:数组值,缓存上下文,默认为空数组(见默认插件类)
cache_max_age:缓存最大时间,整数秒,默认为永久(-1见默认插件类)
class:实例化插件对象的默认实现类,默认为“Drupal\Core\Menu\LocalActionDefault”,当有特殊需要时可以自定义,在默认安装中仅两个定义没有采用该默认类(但都继承了该类),插件id和类如下:
block_content_add_action:
Drupal\block_content\Plugin\Menu\LocalAction\BlockContentAddLocalAction
entity.menu.add_link_form:
Drupal\menu_ui\Plugin\Menu\LocalAction\MenuLinkAdd
菜单本地动作(Menu local actions)插件管理器:
该插件管理器除了收集管理本地动作插件外,还负责为其构造渲染数组,定义如下:
服务id:plugin.manager.menu.local_action
类:Drupal\Core\Menu\LocalActionManager
插件修改钩子:menu_local_actions
获取方法:
$localActionManager =\Drupal::service('plugin.manager.menu.local_action');
使用入口:
$local_actions =$localActionManager->getActionsForRoute($route_name);
这里$local_actions是可以直接返回呈现的渲染数组,包含该路由拥有的所有本地动作,其格式如下:
$local_actions [$plugin_id] = [
'#theme' => 'menu_local_action',
'#link' => [
'title' => $this->getTitle($plugin),
'url' => Url::fromRoute($route_name, $route_parameters),
'localized_options' => $plugin->getOptions($this->routeMatch),
],
'#access' => $access,
'#weight' => $plugin->getWeight(),
];
一个动作按钮一个子元素,此外还会被附加缓存元数据,在以下预处理函数中会进一步处理:
template_preprocess_menu_local_action(&$variables)
该函数使链接被渲染成按钮,对应的默认模板为:
core/themes/classy/templates/navigation/menu-local-action.html.twig
补充:
1、菜单本地动作被渲染成一个按钮,但页面中的按钮不一定就是本地动作,后者是针对整个路由页面的全局操作
2、如何查询目标页面的路由名呢?你可以下载本系列配套的“yunke_help”模块,输入地址即可查询路由参数,或者依据路径到可能的模块下查找路由定义yml文件
3、本地动作是基于路由设置的,是否可以基于url地址呢?答案是不可以,因此本地动作不会指向站外,且系统没有派发关于页面本地动作相关的钩子(插件修改钩除外),模块无法干预页面本地动作块的生成,但如有需求一定要这些“不可以”变成“可以”怎么办呢?在不修改核心的情况下,云客给出一种解决方案:覆写菜单本地动作插件管理器服务,自定义一个继承原插件管理器的类,在自定义类中通过模块处理器派发修改钩子,这又一次体现了drupal的强大灵活和oop开发的优越性。