drupal中覆写可主题化的输出
原文:http://drupal.org/node/173880
译者:葛红儒, Think in Drupal
只有当你需要修改默认输出时,你才需要阅读本节.如果你的显示层是完全有CSS样式表负责的,那么可以略过本节。
覆写主题输出,需要掌握3个方面。首先,你需要知道源头在哪里,其次你要进行覆写,最后你需理解它的类型。
注意,Drupal使用主题注册表(theme registry)来缓存主题数据覆写完成后,你必须清空缓存。
1. 寻找源头:
寻找主题输出的源头,是比较困难的,这是由于主题系统的多层级结构造成的,使得源头可能出现在系统的各个地方。
仅用来演示用。
大多数页面元素一般是由theme('page')拉进来的,在显示导航信息以后,它们被放置在page.tpl.php模板中。页面元素包括主菜单、区块区域元素,区域中的区块等等。通常通过一个主题钩子来引用每个大块的主题化数据。
注意:主题钩子现在包括主题函数和模板两部分。系统中的许多钩子都与主题无关。我们这里提到的钩子都是特定于主题的。
现在使用devel模块(devel module)可以很容易的追踪特定内容的源头。devel模块包含一个主题工具,可以方便的查勘任何输出的源头,类型以及其它主题相关数据。参看示范screencast(http://drupal.org/node/209561)。由于技术方面的限制,它只能应用到Drupal6以及更高版本中。
2. 覆写机制:
覆写机制有一个特定的级联顺序,当然也包含一些特殊情况。Drupal内核和模块使用主题钩子提供了一个合理的默认输出。如果默认输出不符合主题的需求的话,那么就可以对其进行覆写,从而避免使用默认输出。这样,默认的将被放到一边去,我们不再管它,而将所有的特定修改放到所用的主题目录下面。不要直接修改Drupal内核和模块,只在主题目录下面修改。
如果传统的覆写不能满足你的需要的话,你可以使用主题注册表。
注意:尽管在Drupal 6中PHPTemplate.engine还存在,但它已不再覆写主题函数了。在Drupal5中,它允许使用模板来处理部分主题钩子。而现在则不必要这样了。
drupal主题函数 VS drupal模板
3.函数VS模板:
正如前面所说,实现特定的钩子有两种方式。通常的“函数”或者“模板”。根据要主题化的元素的特点,选用最合适的方式。drupal内核和模块可选用任何一种方式来构建输出。而上面的主题层,可以使用同样的方式来覆写,或者改变选用的方式。
使用函数来实现主题钩子,具有速度上的优势。通常比使用模板的快5倍,但是对们对于涉及者来说,就比较困难,通常涉及者都比较熟悉直接的xHTML,而不是php函数。通常,我们不需要考虑这样一点,而是根据钩子的特点和在一个页面中被调用的次数,来决定要选择的方式。
注意:在Drupal5及以前版本,内核和模块只能使用函数来实现主题钩子。想要使用模板的话,必须使用PHPTemplate来覆写钩子,并在引擎层中进行转换。
下面是覆写的两个例子,这里使用了devel themer.
函数方式:
主题函数theme_menu_local_tasks,是一个用来输出一级和二级标签的简单函数。这里的主题钩子就是"menu_local_tasks"。为了覆写它,可将函数名中的前缀"theme"替换为你主题的名字或者所用主题引擎的名字。最好使用主题的名字,这样可以避免潜在的与子主题(http://drupal.org/node/225125)的命名冲突。
本例中,Garland是使用引擎名来覆写的。如果你的主题是基于Garland的子主题,那么你必须使用你的主题名了。
将下面的代码放到主题的template.php,清空主题注册表缓存,这样就覆写了默认输出。注意,将"drop"改为你主题的名字。
[syntaxHighLighter brush="php"]
function drop_menu_local_tasks() { $output = ''; if ($primary = menu_primary_local_tasks()) { $output .= "<ol class=\"tabs primary\">\n". $primary ."</ol>\n"; } if ($secondary = menu_secondary_local_tasks()) { $output .= "<ol class=\"tabs secondary\">\n". $secondary ."</ol>\n"; } return $output; }
[/syntaxHighLighter]
这里所做的唯一修改就是将<ul>标签改为了<ol>。
在api.drupal.org你可以找到所有的主题函数。
模板方式:
如果默认是使用模板实现的,那么你只需要简单得将模板源文件拷贝到主题下面,然后清空主题注册表,就完成了覆写。下面为search-theme-form.tpl.php的一个例子。注意在这里,主题钩子就是"search_theme_form",需要将连字符“-”替换为下划线“_”.
这就是你要做的。使用编辑器,打开拷贝的模板,对其进行修改。内核中的所有.tpl.php文件都带有注释。根据注释,你就可以做出具体的修改了。
注意:模板可以放在主题下面的任何目录中。这样便于管理,也避免了主题根目录下面的混乱。
相关页面:
- 为了定制模板中的变量,参看自页面“预处理函数”(http://drupal.org/node/223430)。
- 可以在子页面“核心模板和建议”(Core templates and suggestions)找到所有的主题模板。
将函数转化为模板
将一个主题函数转化为一个模板,开始是需要一点工作的,但一旦完成,便很好使用。如果你和设计者一同工作,那么转化为模板,将会使设计者更专注于设计,而不是编码。在内核中,已有了很多模板,而在将来的版本中,将有更多的主题函数转化为模板。第3方模块,为了与内核接轨,最好也使用模板。本部分是为那些还没有使用模板的主题钩子准备的。
Drupal以模板的方式识别主题钩子是自动完成的。下面是完成修改所需的所有必要条件:
- 模板名必须与主题钩子匹配。
- 主题钩子中的下划线必须改为连字符。
- 模板文件必须使用扩展名".tpl.php"。(根据主题引擎的不同,扩展名会有所不同)
假如主题函数为theme_user_signature。这里的主题钩子就是"user_signature"。创建一个名为"user-signature.tpl.php"的文件,清空注册表,就会告诉Drupal现在钩子已改为模板方式了。现在该文件中的内容将替代相应的函数。这里的难点是,设置模板文件中用到的变量,这可以通过预处理函数来完成。
需要注意的一些点:
- 可以在模板中直接放置代码,但这种方式不好。所有的复杂逻辑都应该从.tpl.php文件中分离出来。这样使得模板文件更干净,更便于管理。
- 这也有安全方面的考虑。将逻辑与显示分离,可以避免潜在的恶意用户来创建内容,从而减小CSS(cross-site scripting)攻击的机会.当让你的设计者处理模板文价时,所有的输出都应该非常干净,这样设计者就不用考虑安全问题了。
- 比较关于论坛的theming functions in 5和template conversions in 6。你可以使用这个作为例子,来进行两种方式之间的转换。
- 更多关于预处理函数的信息(http://drupal.org/node/223430)。
drupal主题注册表
原文:http://drupal.org/node/173880
译者:葛红儒, Think in Drupal,
Drupal的主体注册表维护了主题钩子相关的缓存数据,包含主题钩子和如何处理它们的信息。
对于大多数drupal主题开发者来说,都不需要直接与注册表打交道。只需要记住,当添加或者删除主题函数和模板时,要清空它。编辑已有的函数和模板时,则不需要清空。
清空主体注册表,有3方式:
- 位于"Administer > Site configuration > Performance"的clear按钮。
- 如果启用了devel区块(devel模块创建的),点击"Empty cache"连接。
- 使用API函数drupal_rebuild_theme_registry。
drupal主题注册表是主题钩子相关信息的缓存数据,包括Drupal可用的主体钩子,勾子类型,即如何处理它们。在以前的版本中,所有的主题调用都是直接完成的。由于在底层需要进行大量的处理工作,而缓存可以加快这种处理,特别是对于模板而言。你主题用到的引擎应该为你自动的注册所有的主题钩子。
在一些特殊情况下,你需要直接与注册表打交道。如果你的drupal主题需要注册一个新的钩子,而该钩子不在底层中(内核,模块,引擎)。比如说一些表单,内核或者模块没有明确对其主体化,而仅仅使用了默认的表单输出。
- 更多细节,参看子页面“特殊情况下的主题注册表”(The theme registry for special cases)。
- 不要将主题注册表与主题的.info文件混淆了,两者都被缓存了。清空主题注册表的第1点和第2点,同时也清空了.info的缓存。
- 预处理函数
- 默认的基本变量
- 特殊情况下的主题注册表
- 使用模板建议(suggestions)
- 核心模板和建议(suggestions)
drupal预处理函数
预处理函数仅适用于模板形式的主题钩子.它的主要作用是设置模板文件((.tpl.php)中所用到的变量。在预处理器(Preprocessor)中,一般涉及不到普通的主题函数。
注意:
- 在提供模板建议(template suggestions)时也会用到预处理器。
- 在drupal5中,函数_phptemplate_variables提供了同样的功能,在drupal6中,为了以后版本的兼容性,最好不要用这个函数。
对于单个主题钩子,可以有多个预处理器。内核,模块,引擎,主题,每层都可以有一个预处理器,来逐步的构建显示在模板文件中的变量集。通过将大部分逻辑放到这些预处理器中,可使得模板文件更加简洁,易于使用。
下面是预期的预处理器。当它们同时存在时,按照下面的顺序运行:
- template_preprocess
-这个是由内核提供的,也是始终存在的。这里声称的变量在所有的模板钩子中都可以使用. - template_preprocess_hook
-实现了主题钩子的内核或者模块提供该处理器。特定于某个钩子的变量,通常首先在这里生成。 - moduleName_preprocess
-不要将这个与前面的预处理器混淆了。对于那些最初没有实现钩子的模块,它允许影响变量集。它将在所有的钩子中运行。 - moduleName_preprocess_hook
-和第3个一样,但是特定于某个钩子。 - engineName_engine_preprocess
-主题引擎的预处理器。适用于所有的钩子。 - engineName_engine_preprocess_hook
-主题引擎的另一个预处理器,特定于单个钩子。 - engineName_preprocess
-这是第一个可以在主题内部使用的预处理器。命名方式为,主题所用引擎名称+预处理器名。适用于所有的钩子。 - engineName_preprocess_hook
-这个和第7个一样,但是特定于单个钩子。 - themeName_preprocess
-命名方式为:主题名+预处理器名。适用于所有的钩子。 - themeName_preprocess_hook
-与前者一样,但是特定于单个钩子。
这里有多种方式可修改变量集。在大多数情况下,只有前两个预处理器存在。第一个,添加了所有的默认基本变量,而第2个添加了特定于该主题钩子的变量。第3方模块,如果用到了第3和第4个预处理器的话,需要添加注释对其进行详细说明。这里就不对此展开讨论了。
尽管可以这样做,但是默认的PHPTemplate没有对变量集进行修改。(5 & 6)
从列表中的第7个开始,所有的预处理器都是放置在主题中的。这个预处理器列表最多是可以超过10个的,那就是使用子主题,子主题是基于第9和第10个预处理的前缀主题名的,但是这种情况在实际中很少用到。
注意:
- 一般推荐在基主题的预处理器中使用引擎名称(7 & 8)。这有利于代码在主题之间的迁移,同时有利于在Drupal.org上发布代码片断。
- 而只有在子主题(sub-themes)中才使用主题名称(9 & 10)。这将减少潜在的重名冲突,在PHP中是不允许重名的。
- 为了识别你主题的预处理器,与钩子相关联的模板必须位于主题内部。如果存在默认的模板的话,将其拷贝到你的主题下面,并清空注册表。如果你要将一个主题函数转化为一个模板,参看前面页面的“以模板方式注册钩子”(http://drupal.org/node/173880#convert-type)。
注意,这些函数中都没有返回值,所有的变量都是通过引用传递的,前面都有符号“&”,比如&$var。
由于这里适用的是引用方式,所以在前面设置的变量,在后面的预处理器中都会存在,所以你一定要小心,不要在这里出什么乱子。重置以前的变量是可以的,但重置以后,你总会疑神疑鬼,感情哪里会出漏子。
这个例子,来自于实现了钩子"foo"的模块:
[syntaxHighLighter brush="php"]
function template_preprocess_foo(&$variables) { $variables['foo_list'] = array( 'list item 1', 'list item 2', 'list item 3', ); }
[/syntaxHighLighter]
在主题的预处理器中添加变量集:
[syntaxHighLighter brush="php"]
function drop_preprocess_foo(&$variables) { // Do not do this unless you mean to: $variables['foo_list'] = array('list item 4'); // Instead do this: $variables['foo_list'][] = 'list item 4'; }
[/syntaxHighLighter]
在模板文件中使用的变量,就是$variables的键。所以,在上面的例子中,在模板文件中可用的变量就是$foo_list。
原文:http://drupal.org/node/223430
译者:葛红儒, Think in Drupal,