模板语言和主题引擎

用Drupal的行话来说,主题就是一组负责你站点外观的文件。你可以从http://drupal.org/project/Themes下载第 3方主题,或者你可以自己动手创建一个主题,后者正是你在本章将要学习的。作为一个web设计者,主题由你所熟悉的大部分内容所组成:样式表,图 片,JavaScript文件,等等。你将发现,在Drupal主题和纯HTML站点之间的区别就是模板文件。这些文件一般都包含大段的静态HTML,和 一些小段的用来插入动态内容的代码。它们负责你站点的一个特定部分的外观。模板文件的语法依赖于它所使用的主题引擎。例如,列表8-1,8-2,8-3列 出了3个模板文件的代码片段,它们输出的内容是一样但是包含的模板文件内容却完全不同。

构建一个PHPTemplate主题

创建一个主题,可以有多种方式,这取决于你的起始材料。假定你的设计者已经为你的站点提供了HTML和CSS文件。那么将设计者的设计转化为一个 Drupal主题,到底难不难呢?它实际上不是很难,而且你能够轻易的完成工作的80%。不过还有20%—最后的难点了—它是 Drupal主题制作高手与新手的分水岭。首先让我们从简单的部分开始。这里有个概括:

  • 为站点创建或修改HTML文件
  • 为站点创建或修改CSS文件
  • 创建一个.info文件,来向Drupal描述你的新主题。
  • 按照Drupal的标准为文件命名。
  • 在你的模板中,插入可用的变量。
  • 为单独的节点类型,区块,等等创建模板文件。

每个theme至少包含一个描述文件.info,其它如果没有则使用系统默认文件。主要包括模板文件,CSS文件等。

理解Drupal自带模板文件

template.php

每个theme都可以包含一个template.php文件,用来包含逻辑代码,这个文件Drupal会自动载入的,我认为这个文件相对于 Drupal模块的.module文件一样。其实一个theme和一个module非常相似,例如.info文件的写法以及template文件 和.module文件的写法非常相似。

所以我可以在template.php文件里,我们可以实现hook_theme等,此时你就认为theme是一个module好了。

theme机制介绍

当Drupal想要为一个可主题化的项目(比如节点,区块,面包屑,评论,或者用户签名)生成一些HTML输出时,它将查找用来为该项目生成 HTML的主题函数或者模板文件。Drupal的所有部分,基本上都是可主题化的,这意味着,对于为该项目实际生成的HTML,你可以进行覆写。

Drupal的主题系统背后的核心哲理和钩子系统的类似。通过遵循命名规范,就可以标识出哪些函数是主题相关的函数,它们负责格式化并返回你站点的内容,或者使用模板文件负责输出HTML内容。

因此我们要输出内容时一定要用theme机制实现,方便维护扩展,实现一个theme输出主要有以下几个步骤:

  • 实现hook_theme(),目的是注册我们的theme,会被写入theme注册表,当调用theme(‘themename’)时会去theme注册表查找该theme。
  • 使用函数或模板输出内容。函数以theme_开头,例如theme_breakcrumb()。如果是模板文件则以.tpl.php结尾。
  • 实现hook_preprocess_HOOK来为我们的输出theme输出准备变量,这步不是必须的。
  • 其它开发人员如果要覆盖你的输出,则在他们的theme中按照一定的规则来覆盖。

下面将详细介绍整个过程,我们假定创建了helloTheme的theme,以及helloModule的module,用于展示我们的代码。

theme_hook介绍

theme_hook通常在module中实现,事实上我们也可以在theme实现theme_hook,例如helloTheme_theme()。因为我们之前说过一个theme某种程度上来说就是一个module。

        function helloModule_theme() {
return array(
//theme_function的写法
'hello' => array(
'variables' => array('abc' => NULL),
), //模板文件的写法
'test' => array(
'variables' => array('abc' => NULL),
'template' => 'test',
),
);
}

theme_hook在Drupal6和Drupal7中写法是有点区别的,例如Drupal7中使用variables来传递变量,每个 theme函数都会有个$variable参数。而Drupal6是用arguments。另外Drupal7中还引入了render element的写法,具体见hook_theme

Drupal自带的每个module基本上都实现了hook_theme,Drupal的核心theme的定义是在System模块里的 system_theme中实现的,里面调用了drupal_common_theme()函数来定义Drupal的核心theme,比如 breadcrumb, table等。

theme函数输出

函数以theme_开头,加上我们注册的theme名称,例如我们上面注册了hello的theme,则该theme函数的函数名为 theme_hello()。我们通过theme(‘hello’, array(‘abc’ => ‘Hello’))来调用我们的theme函数,abc这个参数可以通过$variable来获取。Drupal会为每个theme函数传递一个数组进来 的,里面包含了所有的变量。

        function theme_hello($variables) {
return "You say " . $variable['abc'];
}

是选择theme函数还是theme模板输出,取决于你侧重点。theme函数性能较好,执行较快,但是对于前端开发人员不友好,需要去理解PHP相关知识,而theme模板输出对前端开发人员较友好,但是性能很差。

Drupal核心的theme函数都在includes/theme.inc中定义,比如theme_breadcrumb(), theme_table等。

theme模板输出

根据theme_hook里定义的模板文件名,我们需要在我们的module目录下面创建一个test.tpl.php,在模板文件里,我们可以直 接通过$variables来获取我们传进去的参数,如$variables['abc'],同时Drupal会把参数直接转换成变量,因此我们也可以直 接访问$abc。

        <h2>You say <?php print $abc; ?></h2>

Drupal中核心的模板文件都在各自的module目录下面,比如html.tpl.php, page.tpl.php都在system模块下面,而node.tpl.php在node目录下面。

为输出准备变量hook_preprocess_HOOK

通常我们在输出时用到的数据都是调用时直接作为参数传进去,例如theme(‘hello’, array(‘abc’ => ‘Hello’)),但是以下情形时我们可以调用预处理函数来准备变量:

  • 我们需要非常多的小的变量,如果通过参数传递会太长,因此可以在预处理函数里进行预处理,将一个大的参数拆分成许多小的变量,典型的例子是 node模块为node.tpl.php准备变量,参考node.module中的template_preprocess_node()函数。
  • 我们扩展别人的theme输出,或者不确定我们的参数时,我们可以在预处理函数来处理这些变量。

hook_preprocess_HOOK中的hook是指module名称或theme名称,HOOK是指我们定义的theme的名称,比如helloModule_preprocess_hello(),预处理函数会被自动调用,我们只需要按照命名规则书写就可以了。

我们以page.tpl.php为例来看看预处理函数是怎么工作的。在includes/theme.inc中有个 template_preprocess_page用来给page.tpl.php准备各种变量,如果对page.tpl.php熟悉的话,应该知道 page.tpl.php中有好多变量是可以直接使用的,比如$logo, $tabs, $language等,都是在这里预定义的,在theme函数里,可以通过$variables['logo']来访问,而在模板文件中,Drupal会 把这些变量转换成直接变量,比如logo,我们既可以通过$variables['logo']来访问,也可以通过$logo来访问。

theme输出的覆盖

使用theme机制输出的最大好处就是我们可以用自己的theme输出来覆盖别人的theme输出,从而达到扩展的目的。以上面定义的hello为例,会按照以下的优先级来执行:

        helloTheme_hello()
sites/all/themes/helloTheme/hello.tpl.php
theme_hello()

phptemplate_hello()这种写法在Drupal7中已经被取消了,就是在Drupal7的theme中,所有的前缀必须是themeName + “_”,例如galand_, helloTheme_等。

覆写theme的常见做法就是在自己的theme目录下建tpl模板文件或在temmplate.php中创建theme函数。对于tpl模板文件,同样的文件在theme目录下优先级是更高的,比如我们覆盖node.tpl.php。

hook_preprocess_HOOK的覆写

我们前面说过hook_preprocess_HOOK是用来给theme函数或模板准备变量的,但是它也是有好多写法,有不同的执行顺序的,

        template_preprocess()
template_preprocess_hello()
helloModule_preprocess()
helloModule_preprocess_hello()
phptemplate_preprocess()
phptemplate_preprocess_hello()
helloTheme_preprocess()
helloTheme_preprocess_hello()
template_process()

上面提到的所有函数是从一个到最后一个顺序执行的,就是说,如果上面的函数都存在,就会都执行一遍,如果他们提供了同名的变量,则后面的覆盖前面的。这个和theme输出是不一样的,theme输出只会执行优先级最高的那个。

这里还是以template_preprocess_page为例,这里会先执行template_preprocess_page(),然后在执 行template_process(),如果我们在theme里定义了helloTheme_preprocess_page(),则会在 template_process()之前执行。

Drupal中模板文件命名规则

上面说过,theme下面的同名模板文件比module下面的优先级高,比如helloTheme/node.tpl.php就比node/node.tpl.php优先级高,但是模板文件还可以根据命名的规则来确定优先级:

1、block–[region[module--delta]].tpl.php

基于主题文件: block.tpl.php

block–module–delta.tpl.php

block–module.tpl.php

block–region.tpl.php

2、comment–[node-type].tpl.php

基于主题文件: comment.tpl.php

3、comment-wrapper–[node-type].tpl.php

基于主题文件: comment-wrapper.tpl.php

4、forums–[[containertopic]–forumID].tpl.php

基于主题文件: forums.tpl.php

For forum containers:

forums–containers–forumID.tpl.php

forums–forumID.tpl.php

forums–containers.tpl.php

For forum topics:

forums–topics–forumID.tpl.php

forums–forumID.tpl.php

forums–topics.tpl.php

5、maintenance-page–[offline].tpl.php

基于主题文件: maintenance-page.tpl.php

6、node–[typenodeid].tpl.php

基于主题文件: node.tpl.php

node–nodeid.tpl.php

node–type.tpl.php

node.tpl.php

7、page–[frontinternal/path].tpl.php

基于主题文件: page.tpl.php

page–node–edit.tpl.php

page–node–1.tpl.php

page–node.tpl.php

page.tpl.php

page.tpl.php (this is always a suggestion)

page–node.tpl.php (and prefix is set to page__node)

page–node–%.tpl.php

page–node–1.tpl.php (prefix is not changed because the component is a number)

page–node–edit.tpl.php (and prefix is set to page__node__edit)

page–front.tpl.php (but only if node/1/edit is the front page)

8、poll-results–[block].tpl.php

基于主题文件: poll-results.tpl.php

9、poll-vote–[block].tpl.php

基于主题文件: poll-vote.tpl.php

10、poll-bar–[block].tpl.php

基于主题文件: poll-bar.tpl.php

11、profile-wrapper–[field].tpl.php

基于主题文件: profile-wrapper.tpl.php

12、search-results–[searchType].tpl.php

基于主题文件: search-results.tpl.php

13、search-result–[searchType].tpl.php

基于主题文件: search-result.tpl.php

Theme的调试输出

  • render(), hide()函数,这两个函数是Drupal7新加的,便于可使节点的打印输出更精细,render()用来构造内容,比如print render($page['highlighted']);,因为Drupal对构造过的内容会做标识,下次不会再次构造,因此hide()就是把标识 去掉,可以接着render了。
  • Devel是个强大的Drupal开发工具,主题开发者模块是依赖于Devel的一个模块,能够让你指定一个页面元素,来查看生成该元素所用到的模板文件和主题函数,以及对于该元素都有哪些变量(和它们的值)可用。
  • 注:原文链接:http://blog.csdn.net/wjc19911118/article/details/7752479

Drupal theme_hook的更多相关文章

  1. Drupal 8.2.4安装简体中文步骤

    安装的时候发现很多情况下会出现各种问题,现在写下自己安装成功的步骤: 1.首先官网下载zip安装包drupal-8.2.4.zip 2.下载官方提供的8.2.4简体中文语言包drupal-8.2.4. ...

  2. PhpStorm创建Drupal模块项目开发教程(3)

    rush是 Drupal的脚本界面,PhpStorm的命令行工具支持Drush 5.8和更高版本. 接下来就Drush配置和基本操作进行设置,首先点击打开Settings | Command Line ...

  3. PhpStorm创建Drupal模块项目开发教程(2)

    通常支持Drupal HOOK的文件为.module.首先我们需要在这里对它进行声明,以便索引,并且在代码完成中使用Ctrl+Space(空格)完成HOOK实现. Drupal HOOK调用,通常情况 ...

  4. Joomla软件功能介绍与开源程序大比拼Joomla,wordpress,Drupal哪个好?

    Joomla 软件功能介绍:    Joomla!是一套在国外相当知名的内容管理系统 (Content Management System, CMS),它属于Portal(企业入口网站)类型,顾名思义 ...

  5. Drupal资源

    以下是一些Drupal的常用资源. www.drupal.org:Drupal官网,拥有最全 www.acquia.com:Drupal奠基人Dries主导的专业网站,有著名的Aquia平台,功能类似 ...

  6. Drupal 7.31SQL注入getshell漏洞利用详解及EXP

    0x00 这个漏洞威力确实很大,而且Drupal用的也比较多,使用Fuzzing跑字典应该可以扫出很多漏洞主机,但是做批量可能会对对方网站造成很大的损失,所以我也就只是写个Exp不再深入下去. 0x0 ...

  7. drupal记录(一)

    翻译包下载网址:locallize.drupal.org 中文模块 local 自动下载模块 L10n_update 第三方menu菜单 admin menu,menu bar 打开这个后要关闭系统自 ...

  8. git drupal eclipse

    eclispe如何打补丁https://www.drupal.org/patch/apply打patch,初级详细教程https://www.drupal.org/node/620014

  9. 新版PHP 7效能實測:Drupal 7能快70%,碎形計算大勝Ruby和Python

    PHP 7才剛在12月3日正式釋出,網頁開發框架Zend公司立刻發表了一份PHP新舊版效能大車拼報告,除了PHP 7和PHP 5.6之外,也把HHVM 3.7版納入一起比較. Zend公司選擇了幾套知 ...

随机推荐

  1. Flink生态与未来

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  2. poll?transport=longpoll&connection...烦人的请求

    2016-06-19 11:50 76人阅读 评论(0) 收藏 举报  分类: C#那点事 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.问题描述: 最近使用miniui做了一个后台管理系 ...

  3. shell-004:检测机器存活或者网络陡动情况!

    如下图情况,我们监测的就是此数据,当大于50%了,我们就可以设置告警等! #!/bin/bash # 用ping检测一台机器的存活或者网络波动情况 # 检测机器的丢包率来检测网络波动情况!! n=`p ...

  4. 分布式id生成方法

    系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结.生成ID的方法有很多,适应不同的场景.需求以及性能要求.所以有些比较复杂的系统会有多个ID生成的策略.下面就介绍一些常见 ...

  5. JDK 5 ~ 10 新特性倾情整理!

    JDK 5 ~ 10 新特性倾情整理! 最近连 JDK11都在准备发布的路上了,大家都整明白了吗?也许现在大部分人还在用6-8,8的新特性都没用熟,9刚出不久,10-11就不用说了. 为了大家对JDK ...

  6. Jquery 常用方法 及属性

    Jquery   常用方法 及属性 jQuery 事件 鼠标事件 键盘事件 表单事件 文档/窗口事件 click keypress submit load dblclick keydown chang ...

  7. struts2学习笔记(二)—— struts2的架构【转】

    一.系统架构   Struts2的官方文档附带了Struts2的架构图. 从这张图能够非常好的去理解Struts2 关于图中的Key: Servlet Filters:过滤器链,client的全部请求 ...

  8. bzoj 1189 二分+最大流

    题目传送门 思路: 先预处理出每个人到每扇门的时间,用门作为起点进行bfs处理. 然后二分时间,假设时间为x,将每扇门拆成1到x,x个时间点,表示这扇门有几个时间点是可以出去的.对于一扇门,每个时间点 ...

  9. BZOJ - 1458 / P4311 最大流应用 贪心

    题意:给定n*m的图,每个士兵可以占领当前行和列,第i行至少要R[i]个士兵占领,第j列至少要C[j]个士兵占领,部分网格无法占领,求占领所用最少士兵数,若无解则输出orz 士兵的贡献情况有1(只有效 ...

  10. base64的python实现

    写了一个函数,自己按照base64的规则转换一个字符串. # /usr/bin/python # encoding: utf-8 base64_table = ['A', 'B', 'C', 'D', ...