You are here

逐步分析theme()函数(1)

老葛的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');
 
    第一个函数就是template_preprocess()。你可以在http://api.drupal.org/api/function/template_preprocess/6中查看这个函数的代码,或者也可以直接在includes/theme.inc中查看。这个函数用来设置所有模板中都适用的变量(参看“实用于所有模板的变量”一节)。
   预处理函数是成对儿出现的。第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。

Drupal版本: