You are here

16.4 使用drupal_render呈现页面数组

admin 的头像
Submitted by admin on 星期一, 2015-08-03 10:04

作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com

现在,整个$page数组已经构建完成了,Drupal是怎么把它转为HTML页面的呢?注意这里的这个数组的类型是page,这个和表单元素数组,是一样的。Drupal6里面的表单数组,在Drupal7下,概念上做了进一步的扩充,除了表单元素以外,区块、节点、页面都是以呈现数组的形式出现。所有的呈现数组,经过drupal_render函数处理,就会转换成对应HTML形式。我们来看一下drupal_render的定义。

function drupal_render(&$elements) {

  // Early-return nothing if user does not have access.

  if (empty($elements) || (isset($elements['#access']) && !$elements['#access'])) {

    return;

  }

 

  // Do not print elements twice.

  if (!empty($elements['#printed'])) {

    return;

  }

 

  // Try to fetch the element's markup from cache and return.

  if (isset($elements['#cache'])) {

    $cached_output = drupal_render_cache_get($elements);

    if ($cached_output !== FALSE) {

      return $cached_output;

    }

  }

 

  // If #markup is set, ensure #type is set. This allows to specify just #markup

  // on an element without setting #type.

  if (isset($elements['#markup']) && !isset($elements['#type'])) {

    $elements['#type'] = 'markup';

  }

 

  // If the default values for this element have not been loaded yet, populate

  // them.

  if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {

    $elements += element_info($elements['#type']);

  }

 

  // Make any final changes to the element before it is rendered. This means

  // that the $element or the children can be altered or corrected before the

  // element is rendered into the final text.

  if (isset($elements['#pre_render'])) {

    foreach ($elements['#pre_render'] as $function) {

      if (function_exists($function)) {

        $elements = $function($elements);

      }

    }

  }

 

  // Allow #pre_render to abort rendering.

  if (!empty($elements['#printed'])) {

    return;

  }

 

  // Get the children of the element, sorted by weight.

  $children = element_children($elements, TRUE);

 

  // Initialize this element's #children, unless a #pre_render callback already

  // preset #children.

  if (!isset($elements['#children'])) {

    $elements['#children'] = '';

  }

  // Call the element's #theme function if it is set. Then any children of the

  // element have to be rendered there.

  if (isset($elements['#theme'])) {

    $elements['#children'] = theme($elements['#theme'], $elements);

  }

  // If #theme was not set and the element has children, render them now.

  // This is the same process as drupal_render_children() but is inlined

  // for speed.

  if ($elements['#children'] == '') {

    foreach ($children as $key) {

      $elements['#children'] .= drupal_render($elements[$key]);

    }

  }

 

  // Let the theme functions in #theme_wrappers add markup around the rendered

  // children.

  if (isset($elements['#theme_wrappers'])) {

    foreach ($elements['#theme_wrappers'] as $theme_wrapper) {

      $elements['#children'] = theme($theme_wrapper, $elements);

    }

  }

 

  // Filter the outputted content and make any last changes before the

  // content is sent to the browser. The changes are made on $content

  // which allows the output'ed text to be filtered.

  if (isset($elements['#post_render'])) {

    foreach ($elements['#post_render'] as $function) {

      if (function_exists($function)) {

        $elements['#children'] = $function($elements['#children'], $elements);

      }

    }

  }

 

  // Add any JavaScript state information associated with the element.

  if (!empty($elements['#states'])) {

    drupal_process_states($elements);

  }

 

  // Add additional libraries, CSS, JavaScript an other custom

  // attached data associated with this element.

  if (!empty($elements['#attached'])) {

    drupal_process_attached($elements);

  }

 

  $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';

  $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';

  $output = $prefix . $elements['#children'] . $suffix;

 

  // Cache the processed element if #cache is set.

  if (isset($elements['#cache'])) {

    drupal_render_cache_set($output, $elements);

  }

 

  $elements['#printed'] = TRUE;

  return $output;

}

这里面注意缓存的相关代码,Drupal缓存无处不在。另外需要注意的是,呈现数组,就是一个树状结构,一个枝干下面会有子枝干,子枝干下面又有子枝干,一直递归下去,最后是树叶。将呈现数组转为HTML的时候,也是这样递归调用的,最先转成HTML的,就是最小的单元组成部分,慢慢地合成,最后整个呈现数组彻底转为HTML


Drupal版本: