跳转到主要内容
maramail 提交于 12 June 2015

以下内容是对晴空的主题制作教程的整理。首先感谢晴空老大对drupal中国地区推广的重要贡献,以及drupal中国的各位朋友的贡献。

然而,晴空写的教程我觉得太凌乱,且面向的更多是有做网站基础的朋友,可能不太适合新手阅读,所以我将他的内容精简一下以后,重新发布一下。

对drupal主题的更多深入研究,请看原贴。 http://drupalchina.cn/node/3192

再次感谢所有原作者。

Drupal 版本

1.2.1.01.jpg

一个熟练的Drupal主题开发者会从网站的设计图上看到 各种网页元素,它们可能是一个独立的元素比如网站logo、也有可能是一组元素,比如由几个区块组成的区域——这些元素就是主题开发者们开发主题的过程 中,需要通过Drupal主题系统实现出来的东西。

Drupal整个系统由模块组成,几乎每个Drupal模块(包括系统自带和用户另外安装的)都会创建各自的HTML代码片段,这些片段会被组合成完整的网页。所有和主题有关的函数都用于生成对应的HTML代码,或者用于将各个代码段整合到一起,以形成一个完整的页面。

比如,如果你的页面上有一个主菜单、一个用户登录区块和一个最新文章的views区块(英文block),那么与之对应的 menu(系统主菜单模块)、user(用户管理模块)和views(drupal7常用的模块,需要自行下载,8自带)模块将负责生成对应的HTML代码,而当你在主题中覆写了他们的模板的话,页面的样式效果则会发生变化。

“覆写”的意思是,你需要在主题的templates目录下,制作对应该区块的“.tpl.php”文件。系统会在发现对应文件的状况下,以新的文件代码覆盖系统的默认设计。

具体方式可以参考下图。

1.2.2.01.jpg

这个过程其实和网页设计的过程是一样的,比如,大部分的情况下,设计师设计网页,首先要设计一个logo,然后设计导航条,接下来是banner, 然后侧边栏,最后是内容区域。当然,还有可能包括标签页、页码、文字区、登录框等......他在做设计的时候,是一个元素一个元素设计的,这些元素最终 组合成一个完整的页面。

另外,需要指出的是,我们提到过的区域(region)和区块(block)都是Drupal中的专用术语。你可以把它们和超市中的区域和货架做个 比较。比如超市中分水果区和日用品区。这就是区域。而水果区的不同货架上分别摆放着不同的水果,比如苹果 、梨子、香蕉等—— 它们作为区块共同组成了水果区 。你可以在/admin/structure/blocks页面看到区域和区块相应设置。另外前面说过,区域是在.info文件中定义的。而区块则一般是 由开发人员编写的模块来提供的,当然,你也可以在/admin/structure/blocks页面自定义一个区块。

下面是一个具体的例子,你可以从中清楚看到页面中的区域是如何分布的,最后还标示出了对应的变量:

1.2.1.02.jpg

模板的嵌套

关于页面的构成,Drupal官网上给出了一个很好的图示:

theme7_anatomy.png

从图中你可以看到,几个区块(block.tpl.php)可以组成一个区域(region.tpl.php),然后这些区域被嵌套进page.tpl.php和html.tpl.php中。这些小块不断嵌套,最终组成一个完整页面并呈现在浏览器上。

 

覆写模板文件的时候,你首先需要做的就是将对应的模板文件拷贝到你的主题文件夹中,然后你需要对它进行重命名,以便这个模板只在你需要的元素上起作用。

比如上图中你可以看到很多个不同的区块,他们对应的系统的默认模板文件是block.tpl.php。如果你要针对具体区块进行覆写,你就需要用不同的名字来区分它们。

模板存在一定的等级关系。如以下例子

page--node--9.tpl.php < page--node--%.tpl.php < page--node.tpl.php

模板文件的名字越短,则其作用域就越大。这里所说的名字长度是指名字中所包含的层级。比如上面例子的 page--node.tpl.php,是应用在所有的区块内容之中的模板,而page--node--9.tpl.php则是应用在编号为9的node内容之中的模板,它的作用域要小得多。

你可以在官网的:https://www.drupal.org/node/1089656 (link is external)https://www.drupal.org/node/223440 (link is external)页面中看到关于命名规则更详细的说明。

要注意的是,Drupal7中使用的模板命名是双横线(--)。至于Drupal8,由于使用了新的Twig引擎和其它更多的新特性的加入,大家可以参考其他教程。

另一个容易忽略的事情是views产生的区块,如果名字太长,程序会自动做一个HASH运算,将名字转变为包含 32个字符的字符串,比如当你检查这个区块的代码时,你可能会在这个区块中看到类似这样的ID:block-views- c56a6974e1e747558c4a63b62b968376——如果你看到了不要奇怪。如果你要覆写这个区块模板的话,命名应该是这样 的:block--views--c56a6974e1e747558c4a63b62b968376.tpl.php,当然你也可以把你的view的名字改短一点。

覆写模板文件的时候,你首先需要做的就是将对应的模板文件拷贝到你的主题文件夹中。但是页面上的某个元素或者区块中的HTML到底是在哪里生成的?如何才能找到对应的需要覆写的代码?或者到底应该拷贝哪个文件?

要正确的覆写代码,你应该知道两件事情:其一,这段代码是模板文件还是主题函数控制的;其二,这段代码是由哪个模块负责的。

一般来说像一个节点或者一个区块这样大的元素都是由模板文件生成的,但是比如导航菜单,面包屑之类的东西,则是由主题函数控制的。

通过谷歌浏览器检 查元素的方式你往往可以在CSS类名中找到这个元素是由哪个模块生成的信息。另一个办法是下载安装Devel Themer模块http://www.drupal.org/project/devel_themer),它能自动帮你完成上面的工作,让你可以很清楚的知道页面上的每个元素是由哪个模板文件或者哪个主题函数控制的。不过它可能会拖慢网站运行,以及当你没有设置临时文件夹的时候,它会报错。解决方法之一是在它的设置里关闭Compress temporary files。

如果代码是由核心模块控制的,你应该尝试在系统文件夹内找到对应的文件。你可以在官网的:https://www.drupal.org/node/190815 (link is external) 页面中找到关于核心默认模板的更详细的说明。

如果是由其他贡献模块生成的代码,那么你需要到对应的模块中找对应的.tpl.php文件。比如views的tpl文件在它下面的theme目录下。找到之后打开看看它的代码和页面中的代码是否一致,你也可以加一段自己的代码进去,看看是否会在刷新之后显示出来。如果是的,那说明你找对了。

如果你找不到对应的模板文件,那么说明这段代码是被定义在主题函数中的。你可以在官网的API文档页面(https://api.drupal.org/api/drupal (link is external)) 来搜索相关函数的信息和代码。一般来说你要找的函数都是由 theme_ 或者 template_preprocess_  开头的。然后你可以和页面 中需要覆写的代码进行比较。主题函数的覆写是在template.php文件中进行的。将你要覆写的函数代码复制到template.php文件中,并将 theme_ 替换成你的主题的名字。比如,要覆写theme_breadcrumb(),你应该把对应的代码拷贝到template.php文件中,并 将名字改为yourthemename_breadcrumb()。

模板文件中除了HTML标记之外还包含PHP变量。你可以在Drupal默认的模板文件的注释中找到变量和它们对应的说明。你也可以在Drupal官网找到相应的说明,学习官网的API是学习Drupal的好办法,这里给出几个例子:

https://api.drupal.org/api/drupal/modules%21block%21block.tpl.php/7 (link is external)

https://api.drupal.org/api/drupal/modules%21node%21node.tpl.php/7 (link is external)

https://api.drupal.org/api/drupal/modules%21system%21page.tpl.php/7 (link is external)

Drupal官网上有上千个主题供大家下载和使用。这其中有大概40个基主题。基主题(base theme)也称父主题,他的概念是和子主题 (sub theme)相对应的。在前面讲解Drupal主题的工作机制的时候,我们已经知道,Drupal会为页面提供一套默认的模板,而基主题则修改 了这些默认模板,以求得到“更好的”特性。它们的作用并不是让你直接使用,而是让你在它们的基础之上创建你需要的子主题。

你可以以下方法创建子主题:

1. 下载并启用基主题并且查看它的使用文档。

2. 新建一个主题并在.info文件中声明它是这个基主题的子主题:

base theme = theme_name

3. 从基主题文件夹中找到你需要修改的模板文件并在你的子主题文件夹中覆写它。

你可以在官网的https://www.drupal.org/node/225125找到关于创建子主题的更加详细的说明。

如果你是一个前端工程师,或者你想做一个Drupal Themer的话,你必须学会使用网格系统——至少我是这么认为的,虽然不一定每个项目都会 用到它。最初的网格系统都是固定布局的,那个时候,智能手机和响应式设计还没有面世,这其中最广为使用的是960网格系统。你可以 在 http://960.gs下载并使用。后来,随着响应式设计的兴起,又出现了流式布局的960网格系统,以适应小屏幕上元素自动重新排版的需求。然 后类似的又出现了978网格系统、1140网格系统。人们还在这些网格系统中加入了其他特性,如图标,按钮,JS特效等特性,形成了各种复杂的前端框架, 比如YUI、Blueprint、Square Grid、Boilerplate以及现在在国内很流行的Bootstrap3。这些都是知名的前端框 架。同时,你也可以在Drupal官网上找到与它们相对应的基主题。使用这些基主题的好处是,比如网格,响应式设计甚至图标,按钮,JS特效等特性都已经 为你提前处理好了,在合理使用的情况下,原则上应该能为你节约很多时间。

在主题中使用网格系统的方法有两种,其一是直接下载你需要的网格系统,并在主题中引用他们,其二是直接使用对应的基主题。

我们在第二章中已经说过,模版文件中包括Html和php。上节中在绘制线框图的过程中,也建议大家标明PHP变量,比如上图中出现 的$logo,$main_menu ,$secondary_menu 。至于这些变量的定义及作用,其实就好像乘法口诀表一样,最好能够熟记。在模版开发的过程中,你会发现,最经常被覆写的模版分别是:html、page、 node和block。以下4幅图片分别给出了对应的模版文件中的变量及其定义:

2014-08-13_072914.png

2014-08-13_072908.png

2014-08-13_072901.png

2014-08-13_072854.png

同时,这些说明也会出现在注释段落中

基模板: block.tpl.php

模板建议:block--[region|[module|--delta]].tpl.php

可能的模板:

1. block--module--delta.tpl.php

2. block--module.tpl.php

3. block--region.tpl.php

“module”是模块的名称、“delta”是由模块指定的区块ID。

比如我们用自定义区块功能定义的第一个区块,其相应的模板文件命名为:“block--block--1.tpl.php”这其中第二个 “block”的含义是:这个区块是由核心的block模块生成的。“1”的含义是生成的第一个模块,该区块的delta值为1。“region”会在相 对应的区域上生效,例如:“block--sidebar_first.tpl.php”,这其中的“sidebar_first”就是一个在.info 文件中定义的区域。(值得注意的是,这里的下划线被保留了)

如果你有一个叫做“custom”的自定义模块生成了一个ID为“my-blcok”的区块,那么当你为这个区块定义自己的模板时,你就应该把模板命名为“block--custom--my-block.tpl.php”

如果你用views模块生成了一个视图名为“front_news”,ID为“block_1”的区块,那么这个区块的模板建议应该是“block--views--front-news-block-1.tpl.php”(值得注意的是,这里的下划线应该被转换成短横线)

上面的“module”是模块的名称,如果你有一个叫做“MyModule”的模块生成了一个区块,这个区块的模板建议应该是“block-- MyModule.tpl.php”,如果你的模块叫做“xxx”,那么这个区块的模板建议应该是“block--xxx.tpl.php”。不过,请你 别把模块命名为xxx,写程序的人很多都是偏执暴力狂,他们看到这样的名字往往会发病。

其余的模板建议可以在官网找到:https://www.drupal.org/node/1089656。由于内容的相似性,这里不对其余模板建议进行详细描述,仅列举部分如下,请注意,标有序号的都是可

选的模板,但是越是排在前面的作用范围越小,优先级也越高,即查找顺序从上至下:

评论:comment--node-[type].tpl.php  

基模板:comment.tpl.php

如果对某内容类型为“article”的节点进行评论,则模板建议为“comment--node-article.tpl.php”

comment-wrapper--node-[type].tpl.php  同上

基模板:comment-wrapper.tpl.php

 

字段:field--[type|name[--content-type]|content-type].tpl.php

基模板:field.tpl.php

1.field--field-name--content-type.tpl.php

2.field--content-type.tpl.php

3.field--field-name.tpl.php

4.field--field-type.tpl.php

注意这里的name指的是字段的机读名称,并且这个机读名称中的下划线会被短横线所替换。并且自定义字段的名字前面要加上“field-”如:“field--field-phone.tpl.php”

论坛:forums--[[container|topic]--forumID].tpl.php

基模板:forums.tpl.php

For forum containers:

1. forums--containers--forumID.tpl.php

2. forums--forumID.tpl.php

3. forums--containers.tpl.php

For forum topics:

1. forums--topics--forumID.tpl.php

2. forums--forumID.tpl.php

3. forums--topics.tpl.php

 

HTML模板:html.tpl.php

如下是两个例子:

html--internalviewpath.tpl.php

html--node--id.tpl.php