跳转到主要内容
云客 提交于 23 December 2016

本篇主题讲解drupal8系统是如何计算页面标题的,标题很重要,尤其对于搜索引擎优化来说,标题权重很高

页面有标题当然是针对请求格式为html而言,在整个执行流程中如果控制器直接返回响应对象,那么标题计算就在控制器中随意进行 流程仅仅停留在Symfony的渲染管道中,如果控制器返回的是渲染数组,那么将派发视图事件,主内容视图订阅器MainContentViewSubscriber将判断请求格式,并启动对应的格式渲染器渲染输出 今天的话题就发生在请求格式为html的HtmlRenderer渲染器中,这个渲染器用到了标题解析器 这就是本主题的内容,下面看看标题是怎么计算出来的:

首先如果控制器返回的渲染数组包含#title子元素,如:$main_content['#title'],那么将原封不动的使用其值,标题计算完成 如果没有包含,则调用标题解析器进行计算,标题解析器服务id为“title_resolver” 类:Drupal\Core\Controller\TitleResolver 构造函数接收控制器解析器:controller_resolver及字符串翻译服务:string_translation

下面看一下标题解析源代码:

 

public function getTitle(Request $request, Route $route) {
    $route_title = NULL;
    // A dynamic title takes priority. Route::getDefault() returns NULL if the
    // named default is not set.  By testing the value directly, we also avoid
    // trying to use empty values.
    if ($callback = $route->getDefault('_title_callback')) {
      $callable = $this->controllerResolver->getControllerFromDefinition($callback);
      $arguments = $this->controllerResolver->getArguments($request, $callable);
      $route_title = call_user_func_array($callable, $arguments);
    }
    elseif ($title = $route->getDefault('_title')) {
      $options = array();
      if ($context = $route->getDefault('_title_context')) {
        $options['context'] = $context;
      }
      $args = array();
      if (($raw_parameters = $request->attributes->get('_raw_variables'))) {
        foreach ($raw_parameters->all() as $key => $value) {
          $args['@' . $key] = $value;  //@和%表示要进行转义的状态,见下文解释
          $args['%' . $key] = $value;
        }
      }
      if ($title_arguments = $route->getDefault('_title_arguments')) {
        $args = array_merge($args, (array) $title_arguments);
      }

      // Fall back to a static string from the route.
      $route_title = $this->t($title, $args, $options);
    }
    return $route_title;
  }

 

首先查找路由定义中是否设置有标题回调,设置格式和控制器完全一样,键名为_title_callback,对回调的执行和控制器完全一样 通过标题回调得到的结果不会被翻译,需要翻译需要在回调中进行 如果没有设置回调则查找_title子元素,如果设置了则进行翻译工作(翻译系统介绍请看后续主题 检查是否设置翻译上下文_title_context 此上下文用于翻译过程的消除歧义,比如may 到底翻译成“可以”还是“五月”呢?一般为空 准备翻译参数,将请求中的_raw_variables值放入参数数组,_raw_variables仅包含占位符变量的原始值,不包括路由额外提供的变量 然后检查路由是否提供额外标题参数,如果有则合并入参数数组

然后将标题、参数、上下文传递给翻译系统进行翻译,标题计算工作完成

优先级总结:控制器指定 》标题回调 》路由标题指定

关于翻译系统的参数解释见:https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Render%21FormattableMarkup.php/function/FormattableMarkup%3A%3AplaceholderFormat/8.2.x

翻译系统上下文解释见:https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Language%21language.api.php/group/i18n/8.2.x

 

下面给出一个完整冗余的标题路由定义:

 

yunke.content:
  path: '/yunkehello'
  defaults:
    _controller: '\Drupal\yunke\Controller\HelloController::content'
    _title_callback: '\Drupal\yunke\Controller\HelloController::getTitle'
    _title: 'Hello @user ! time:@May'
    _title_context:'Long month name'
    _title_arguments: 
      @May: "May"
      @user: "yunke" 
  requirements:
    _permission: 'access content'

 

 

我是云客,【云游天下,做客四方】欢迎转载,但须注明出处,讨论请加qq群203286137

 

 

Drupal 版本