注册表是如何构建的

老葛的Drupal培训班 Think in Drupal

当启用一个新的主题时,就会重新构建主题注册表,此时它按照下面的顺序来查找主题钩子:
 
1.首先,它查找有哪些模块实现了hook_theme(),从而找到这些模块提供的主题函数和模板文件。
 
2. 如果该主题是基于另一个主题的,那么首先会调用基主题引擎中的hook_theme()实现。例如,Minnelli是一个基于Garland的主题。它的基主题的主题引擎为PHPTemplate。所以会调用phptemplate_theme()来查找前缀为phptemplate_或garland_的主题函数,以及基主题目录下按照特定方式命名的模板文件。例如,模板文件themes/garland/node.tpl.php就添加到了这里。
 
3. 调用该主题的hook_theme()实现。所以,对于Minnelli,将会调用phptemplate_theme()来查找前缀为phptemplate_ 或minnelli_的主题函数,以及该主题目录下的模板文件。所以,如果Minnelli在themes/garland/minnelli/node.tpl.php提供了一个节点模板,那么它就会被发现。
 
    注意,在每一步中,新发现的主题函数和模板文件,能够覆写注册表中已有的主题函数和模板文件。这就是继承的机制,它允许你覆写任意的主题函数或者模板文件。
    让我们更进一步的检查一下,在模块中是如何实现hook_theme()的。这个主题钩子的任务是,返回一个包含可主题化项目的数组。当一个项目通过主题函数主题化时,函数的参数也会被包含进来。例如,面包屑是由函数theme_breadcrumb($breadcrumb)负责主题化的。在一个假定的foo.module模块的主题钩子中,通过下面的方式来说明面包屑是可以主题化的:
 
/**
 * Implementation of hook_theme().
 */
foo_theme() {
    return array(
        'breadcrumb' => array(
            'arguments' => array ('breadcrumb' => NULL),
        );
    );
}
 
    如果传递过来的参数为空,那么就使用NULL作为默认值。现在你已经描述了该项的名字和它的参数,并给出了参数的默认值。如果你的主题函数,或者模板预处理函数是包含在另外的一个文件中的,那么你需要使用file键把它包含进来:
 
/**
 * Implementation of hook_theme().
 */
function user_theme() {
    return array(
        'user_filter_form' => array(
            'arguments' => array('form' => NULL),
            'file' => 'user.admin.inc',
        ),
        ...
    );
}
 
    如果你需要声明,一个可主题化项目使用的是模板文件,而不是主题函数的话,你可以在主题钩子中定义模板文件的名字(不带扩展名.tpl.php):
 
/**
 * Implementation of hook_theme().
 */
function user_theme() {
    return array(
        'user_profile_item' => array(
            'arguments' => array('element' => NULL),
            'template' => 'user-profile-item',
            'file' => 'user.pages.inc',
        ),
        ...
    );
}
 
    在前面的user_profile_item例子中,模板文件是通过template键指定的,可以在modules/user/user-profile-item.tpl.php找到。模板的预处理函数位于modules/user/user.pages.inc中,名为template_preprocess_user_profile_item()。template_preprocess()中定义的变量,以及在键arguments中定义的变量$element,都会被传递给template_preprocess_user_profile_item()。变量$element的值,在显示期间被指定。

Drupal版本: