drupal使用的路由系统很强大,在系统中是一个比较大的子系统,它基于Symfony路由组件,所以请务必先学习Symfony的路由组件。
Symfony路由组件的官网文档地址是:http://symfony.com/components/Routing
路由是什么呢?就是一个请求到达后决定由谁去处理的系统,它决定着处理流程的去向,一些比较小的系统路由设计会针对网址特定的格式或元素判断谁来处理,比如常见的MVC,著名的CI框架就在网址中包含控制器、视图、模型信息来判断流程去向,然而drupal8使用的路由系统非常强大,远不止于此,它不但对url没有特征要求,还可以针对请求方法、浏览器代理标识符、上传内容类型、网址部分的正则格式等等来控制,这样能使用任意有表达力的字符串,与系统内部特征解耦,是一个全功能的路由系统。
drupal路由系统目的很简单,就是将一个请求转换为一组变量,这些变量包含需要的控制器、默认参数、访问控制等等内容,系统将这些变量保存在请求对象的$request->attributes属性包中,以供后续参数解析、控制器解析流程使用。
在本系列的《云客Drupal8源码分析之核心处理流程HttpKernel(drupal8执行流程)》中已经说明系统执行的主流程,路由系统是在核心派发出 'kernel.request' 事件时参与执行的,注册的侦听器为router_listener,在其onKernelRequest方法中执行流程进入路由系统,整个路由系统以服务router作为api接口,drupal权限检查在路由中进行,权限管理服务的服务id为:access_manager,由于权限控制是一块很大的内容,另外开一个主题讲解,本篇仅讲路由系统,也就是没有访问检查的路由系统,服务名为:router.no_access_checks,我们先从路由使用角度来看一看怎么定义一个路由:
在核心和模块中使用name.routing.yml(name为模块名)来定义自己相关的路由,在这个文件中可以定义多个路由,下面看一看单个路由是怎么定义的,这是一个全面的列子:
yunke.content:
path: '/yunke/{book}/{page}'
host: "{subdomain}.example.com"
schemes: [https]
methods: [GET, HEAD]
defaults:
_controller: '\Drupal\yunke\Controller\book::show'
_title: 'Hello World !'
book:'drupal'
page:1
subdomain: m
requirements:
_permission: 'access content'
page: \d+
subdomain: m|mobile
_format: 'json|html'
options:
_route_filters: 'yunke__route_filters'
no_cache: TRUE
它们存储在yaml文件中,必须遵循yaml格式,否则yaml解析器会报错,下面来解释每个部分:
路由定义中各元素含义:
yunke.content:表示路由名,在系统内部用作机器名,代表这一条路由,一个yaml文件中可以定义多个路由,但drupal整个系统中路由名必须唯一,以下为它的第一级元素:
path:
必须项,字符串值,且必须以/开始的一个路径,可变动的部分用花括号包起来,形成一个路径变量,里面的字符为占位符名,第一个路径段不能使用路径变量
host:
可选,字符串值,限定可匹配此路由的主机名,同样可以使用{}来包含可变部分形成一个路径变量,未指定则任意
schemes:
可选,数组值,可以使用的协议名,未指定则不限制
methods:
可选,数组值,可以使用的请求方法名,未指定则任意
defaults:
必须项,数组值,代表默认值,里面可以包含系统默认值如控制器、标题等,及路径变量默认值(用占位符名指定)
requirements:
必须项,数组值,约束选项,包含权限需求、路径变量须对应的正则格式、请求内容格式等等
options:
可选,数组值,本条路由的默认选项,用给路由系统本身提供额外信息,比如自动路由过滤器、缓存属性等等
来看一看以上元素可能的值(第二级值):
defaults能包含以下值:
_controller: 指定一个回调 (最常见的是classname::method,它不是路径,而是完全限定的名字空间类名,会被自动加载器加载)可以返回一个渲染数组,它将被模板渲染,也可以返回一个响应对象,它会直接发送给客户端
_form: 指定一个Drupal\Core\Form\FormInterface的实现
_entity_view: 指定entity_type.view_mode. 用给出的视图模式查找实体并渲染
_entity_list: 指定entity_type
_entity_form: 类似_form 但为实体提供一个编辑表
_title (可选): 路由后对应页面