drupal_render()函数接收一个结构化的数组作为参数,然后调用theme()输出HTML。
function drupal_render(&$elements) { ... ... }
$elements['#printed']控制是否已经执行过,避免重复执行。在drupal_render()的开头检查它是否有设置,对应的,在drupal_render()的结尾设置它。
// Do not print elements twice. if (!empty($elements['#printed'])) { return ''; } // 在drupal_render()结尾会设置#printed $elements['#printed'] = TRUE;
$elements['#cache']控制是否允许使用缓存。如果有缓存,就直接返回,不用再重复执行后面的代码。|
// 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; } } // 在drupal_render()结尾保存缓存 if (isset($elements['#cache'])) { drupal_render_cache_set($output, $elements); }
$elements['#pre_render']是一个function数组,drupal_render()会依次执行其中的function,这样可以在render之前对$elements再做一些修改。
// 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); } } }
$elements包含两类项目:properties和children。properties以#开头,其它都是children。
// Get the children of the element, sorted by weight. $children = element_children($elements, TRUE);
$elements['#children']是一个字符串,临时保存drupal_render()输出的内容。
// Initialize this element's #children, unless a #pre_render callback already // preset #children. if (!isset($elements['#children'])) { $elements['#children'] = ''; }
$elements['#theme']控制调用的theme function,结果保存在临时变量$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); }
如果$elements['#theme']没有被处理,对应的$elements['#children']就为空。这个时候,drupal_render()就循环$children,递归调用drupal_render()。注意这里返回的结果是串联在$elements['#children']。
// 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]); } }
$elements['#theme_wrappers']是一个function数组,循环依次传入到theme()。注意这里返回的结果每次都会覆盖掉$elements['#children']。
// 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); } }
$elements['#post_render']也是一个function数组,可以对生成的$elements['#children']做二次处理。注意这里返回的结果每次都会覆盖掉$elements['#children']。
// 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); } } }
$elements['#prefix']和$elements['#suffix']允许对输出HTML做最后修饰。
$prefix = isset($elements['#prefix']) ? $elements['#prefix'] : ''; $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : ''; $output = $prefix . $elements['#children'] . $suffix;