为什么路由文件中带有下划线?


24

带或不带下划线前缀的所有参数的处理方式是什么?

Drupal在哪里决定如何处理这些参数?

这个概念是从Symfony引入的,还是Drupal的新概念?

示例node.routing.yml):

node.overview_types:
  path: '/admin/structure/types'
  defaults:
    _controller: '\Drupal\Core\Entity\Controller\EntityListController::listing'
    entity_type: 'node_type'
    _title: 'Content types'
  requirements:
    _permission: 'administer content types'

2
这是一个Symfony约定。有一个很好的文章在这里,找到写着位的最后一件事要注意在参数名下划线字符的特殊含义。这个字符开头的参数具有特殊的意义
克莱夫

1
谢谢克莱夫。本文提到“特殊含义”,但根本没有解释。为什么非下划线参数也不能特殊?
丹尼尔(Daniel)

1
大声笑,为什么非下划线参数也不能特殊?,这听起来像是一个深切存在的问题!通常(只是通常)使用前缀变量来表示“私有”变量(此处不太可能),或者有助于避免与系统中其他类/方法/其他东西的命名冲突。希望能看到官方文档,是的
Clive

Answers:


41

希望在路由系统的概念以及它的drupal附加功能背后有一个很好的解释。

总体概述

Symfony组件在这里有两个重要概念。http内核是一个获取请求的系统,以某种方式要求其他系统生成以定义代码段,该代码段生成请求的输出(响应对象)并将响应发送回客户端。这段代码称为控制器,因此它可以是纯php4之类的函数,对象上的方法甚至是匿名函数。

知道哪个控制器负责当前请求的系统是路由系统。

在此处输入图片说明

基本路由文件

作为模块开发人员,您可以定义路由列表和相应的控制器。

这是json响应的示例:

taxonomy.autocomplete_vid:
  path: '/taxonomy/autocomplete_vid/{taxonomy_vocabulary}'
  defaults:
    _controller: '\Drupal\taxonomy\Controller\TermAutocompleteController::autocompletePerVid'
  requirements:
    taxonomy_vocabulary: \d+

大多数symfony文档都提到了模式,但是drupal决定只允许其路由文件中使用不建议使用的“ path”键。

关键概念是控制器,该控制器从系统获取一些参数并将其转换为响应。在此示例中,您具有参数“ taxonomy_vocabulary”。因此,没有下划线的所有内容都被视为控制器的参数。如果要指定默认值,则将其放入默认数组。在同一yml数组中,您指定与'::'连接的类和方法,以告诉系统在哪里查找内容。其他所有属性均与控制器参数无关,因此被视为内部属性,因此下划线作为前缀。

Symfony本身还允许您定义正则表达式以验证传入的参数是否有效(使用“ requirements”)。在这里它将仅匹配数字。

控制器解析器

一旦symfony发现当前请求中哪个控制器处于活动状态,它将要求所谓的控制器解析器创建该控制器的实例,可以通过call_user_func_array执行该实例。控制器解析器有一种方法来获取可调用的控制器(对象+方法,匿名函数),以及一种方法来获取传递给控制器​​的参数,请参阅控制器解析器。

Drupal扩展

这基本上就是symfony给您的。

Drupal虽然稍微复杂一些:

  • 您可以检查对路线的访问。例如,在Drupal 7及以下版本中,调用user_access()很常见。
  • 您不想将taxonomy_vocabulary转换为其实际的实体对象
  • 您不希望生成完整的页面响应,而只是“主要内容”。

访问检查

Drupal在symfony部分之上引入了一个系统,该系统检查用户是否有权访问当前路由,并选择抛出403(拒绝访问)异常。存取管理员

在路由文件中,您可以在需求部分中指定它。示例中列出了最常见的位:

  path: '/user/{user}'
  options:
    _access_mode: 'ANY'
  requirements:
    _permission: 'access user profiles'
    _entity_access: 'user.view'
    _role: 'administrator'

_permission定义了对user_access()的调用,_role确保用户具有特定角色(您可以通过,对于OR和+对于AND逻辑指定多个角色)。_entity_access询问实体系统您是否有权查看用户实体。默认情况下,drupal确保您添加了访问检查器,以允许您继续进行操作,但是可以通过_access_mode在选项中进行切换。

上流

如清单中所述,您不需要担心加载实体,请参见/ user / {user}作为示例。对于实体,您基本上只使用实体类型的名称,它将执行带有URL中传递的ID的entity_load。参数转换器管理器

页面响应

如前所述,控制器负责生成响应对象。这在Drupal中将是可怕的,因为页面由其区域中出现的所有块,html和页面模板等组成。因此,drupal指定了不同的键来指定返回页面内容的控制器:

user.page:
  path: '/user'
  defaults:
    _content: '\Drupal\user\Controller\UserController::userPage'
  requirements:
    _access: 'TRUE'

定义的字符串是用于为页面的主要内容区域生成渲染数组的控制器。

表单的另一种添加方式是如何处理表单,因为使用表单返回页面要比仅渲染数组稍微复杂一些,因此可以使用负责当前表单的FormInterface定义_form。

user.pass:
  path: '/user/password'
  defaults:
    _form: '\Drupal\user\Form\UserPasswordForm'
  requirements:
    _access: 'TRUE'

注意:从我的角度来看,这涵盖了最重要的要点,尽管肯定还有很多要讨论的要点。

TL; DR

  • 为不是控制器参数的所有内容指定下划线。这是symfony的一种“标准”。
  • 这些参数通过参数转换器上载,并使用控制器解析器传递给控制器
  • Drupal有一些附加功能,使人们可以更轻松地与symfony路由系统进行交互。

哇。令人印象深刻的答案。为什么某些参数中有句点而不使用下划线?例如user.pass(在上面的示例中)与user_pass。那也是symfony的约定吗?
chrisjlee

2
使用$ module。$ name作为路由的机器名有某种约定。尽管没有任何内部假设。
Daniel Wehner

根据以下问题,不再使用_content,而是使用_controller。因此,“ 页面响应”部分中的示例不是最新的。drupal.org/node/2378809如果我们想在页面的内容区域中显示数据,则控制器将定义一个渲染数组,类似于在Drupal 7中的处理方式。如果我们要绕过它,并创建我们的页面从头开始,然后我们可以返回Response对象。
benelori

可以肯定,您不能指望1.5年不会发生
Daniel Wehner 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.