老葛的Drupal培训班 Think in Drupal
首先,传递给theme()函数的参数现在可以使用了。在这里,传递的参数有$node, $teaser, 和$page。所以,对于注册表参数条目中所列的每个参数,Drupal将为其分配一个对应的变量:
$variables['node'] = $node;
$variables['teaser'] = $teaser;
$variables['page'] = $page;
接着,默认的呈现函数将设置为theme_render_template(),而默认的扩展名将设置为.tpl.php(PHPTemplate模板的标准文件扩展名)。呈现函数负责将变量传递给模板文件,一会儿你就会看到。
模板中所用的其它变量则由模板预处理函数提供。首先,对于所有的主题化项目,不管该项目是一个节点,区块,面包屑,或者其它你有的东西,都会调用template_preprocess(),。而第2个预处理函数则是特定于正在呈现的项目的(在这里就是一个节点)。图8-7显示,为节点定义了两个预处理函数,这样调用它们:
template_preprocess($variables, 'node');
template_preprocess_node($variables, 'node');
预处理函数是成对儿出现的。第2个预处理函数名称的最后部分,对应于当前正被主题化的项目。template_preprocess()运行完以后,现在就运行template_preprocess_node()了。它添加了以下变量:$taxonomy, $content, $date, $links, $name, $node_url, $terms, 和$title。这显示在template_preprocess_node()的代码中。注意,数组$variables中的每一个条目,都将变成一个单独的变量,以供模板文件使用。例如,对于$variables['date'],在模板文件中,将简单的作为$date来使用:
/**
* Process variables for node.tpl.php
*
* Most themes utilize their own copy of node.tpl.php. The default is located
* inside "modules/node/node.tpl.php". Look in there for the full list of
* variables.
*
* The $variables array contains the following arguments:
* $node, $teaser, $page
*/
function template_preprocess_node(&$variables) {
$node = $variables['node'];
if (module_exists('taxonomy')) {
$variables['taxonomy'] = taxonomy_link('taxonomy terms', $node);
}
else {
$variables['taxonomy'] = array();
}
if ($variables['teaser'] && $node->teaser) {
$variables['content'] = $node->teaser;
}
elseif (isset($node->body)) {
$variables['content'] = $node->body;
}
else {
$variables['content'] = '';
}
$variables['date'] = format_date($node->created);
$variables['links'] = !empty($node->links) ?
theme('links', $node->links, array('class' => 'links inline')) : '';
$variables['name'] = theme('username', $node);
$variables['node_url'] = url('node/'. $node->nid);
$variables['terms'] = theme('links', $variables['taxonomy'],
array('class' => 'links inline'));
$variables['title'] = check_plain($node->title);
// Flatten the node object's member fields.
$variables = array_merge((array)$node, $variables);
...
}
关于这些变量都是干什么的,可以参看本章前面的部分。
在分配了变量以后,一些疯狂的事情发生了。节点本身从一个对象转化为了一个数组,并与已有的变量合并在了一起。所以,所有的节点属性现在都可以应用在模板文件中了,只需要在属性名前面加个前缀$就可以了。例如,$node->nid现在就可作为$nid来使用。如果一个节点的属性和一个变量拥有相同的名字,那么变量优先。例如,$title包含了$node->title的普通文本版本。当合并发生时,将会在模板文件中使用这个普通文本版本。注意,原始的标题仍然可以通过$variables['node']->title来访问,不过在使用它以前,为了安全考虑,你需要对其进行过滤(参看第20章)。
好了,Drupal现在运行完了预处理函数。现在需要做一个决定:将所有的这些变量传递给哪个模板文件呢?也就是为节点使用哪个模板文件呢?为了做出决定,Drupal进行以下检查:
1. 是不是在
$variables['template_files']中定义了一些模板文件?这里定义的条目都是Drupal将要查找的模板文件的名字。在我们的例子中,节点的类型为story,所以node-story定义在这里;Drupal首先会匹配一个特定内容类型的模板文件,找不到的话再使用通用的节点模板。更多详细,参看http://drupal.org/node/190815。
2.是否设置了$variables['template_file']?如果设置了,优先采用。
函数drupal_discover_template()负责决定采用哪个模板文件。首先,它会找到主题注册表条目中定义的主题路径,然后在这些路径下查找模板文件。在我们的这种情况下,它首先会查找themes/bluemarine/node-story.tpl.php,接着查找modules/node/node-story.tpl.php。如果一个文件也不存在的话(在我们的例子中,一个也不存在:节点模块没有在它的目录中提供特定节点类型的模板文件,而Bluemarine也没有为story节点单独提供一个模板----只有一个通用的节点模板),那么第一轮的模板查找就失败了。接着,Drupal将路径,模板文件,和扩展名串联起来,并对其进行检查:themes/bluemarine/node.tpl.php。嗯,这个文件存在,接着Drupal将调用呈现函数(记住,那就是theme_render_template()),并将选择的模板文件和变量数组传递过来。
呈现函数将变量传递给模板并执行它,然后将结果返回。在我们的例子中,结果就是执行了themes/bluemarine/node.tpl.php所返回的HTML。