区域的定义
在第二章中,我们已经提过区域和区块的概念了,这一节我们会再深入探讨相关问题,因为你画线框图的时候,大部分的时候就是在绘制各种区域和区块。
Drupal用区域来放置网页页面元素。其中大部分的元素是以区块的形式存在于区域中的。区块可以是任何东西,比如一个页面的主要内容(也就是node),一个搜索框,一个导航菜单,一段最新的评论。你可以自己定义一个区块,但是大部分的时候区块是由开发人员编写的模块提供的。因此,在你决定使用某个模块的时候要对其有一定的了解。
区域的尺寸可大可小,最宽可以是全屏的banner,最窄可以只占用一列——这个列是网格系统中的单位。因此,如果你创建的是自己的主题,那么区域的尺寸只由HTML和CSS决定。一般来说在Drupal页面中,最大的区域是用来放置页面主内容的,而最小的区域中只放置一个小的区块。
下图展示的是Fusion基主题的区域设置,你同时可以看到网格系统的使用:
默认情况下,Fusion预设了12个区域可供使用。下图是基于上图的一个案例:
值得注意的是,从一开始就设置足够多的区域,能够更好的适应网站上线之后的发展情况。也许在网站建设阶段你用不上全部的区域,但是随着网站的发展壮大和访问量的增加网站可能会添加新的内容类型、增加不同来源的广告区块等,也有可能在后期你会希望把原本为一列宽的页脚分成三列。
Drupal的默认区域
Drupal核心已经为你定义了9个默认的区域。如下:
在某个主题定义自己的区域之前,Drupal会使用这默认的9个区域。如果某个主题定义了自己的区域,那么默认的区域就不再起作用了,这同样也被视作覆写。同理,如果你的页面布局正好符合这9个默认的区域,那么你就不需要在你的info文件中对区域进行定义。
然而,每次都在你的info文件中包含上面的代码是一种好的实践。一旦你在自己的.info文件中定义了一个区域,就会覆写掉全部的默认区域。所以,推荐的做法是拷贝上面的默认区域定义代码到你的.info文件中,并且将不需要的区域注释掉,而不是将他们直接删除掉,这样做的好处是能让你更容易追踪做过的事情,以保持项目的可维护性。
如果你定义了自己的区域,你还需要用对应的代码将它输出到页面上,这个内容将在下一章讲述。目前,你只需要知道,page_top和page_bottom区域是在html.tpl.php中输出的,而其他的区域都是在page.tpl.php中输出的。
.info文件中必须包含的区域
上面已经说过了,由于默认区域的存在,你不需要在.info文件中定义区域,但是如果你要自己定义区域的话,就一定要包含以下几个区域:
page_top, content和page_bottom
它们的存在是Drupal系统正常工作的一个前提条件。
关于.info文件的写法、page_top和page_bottom区域的作用,更加详细的说明请阅读:4.3 .info文件和4.4 html.tpl.php文件。
Content区域和Main page content区块
Content区域是用来输出页面主要内容区块的。这个区块比较特别,他在中文版drupal7的区块配置界面中,被错误的翻译为:主页内容,并且,你可以把他配置到其它任意区域,或者把它拖拽为禁用(注意这里你只能拖拽,下拉菜单里面却没有禁用的选项),但是,内容依然会显示出来。这个内容是通过page.tpl.php中的$page['content']变量输出的。
高级的区块输出方式
我们前面已经说过了,在Drupal中,你通过.info文件来定义区域,然后通过后台区块设置界面定义和控制区块,并将它们放入你定义好的区域中,然后在page.tpl.php模版中把区域输出到页面上。这样做的好处是简单,输出区域的代码很直观很简单,对于没有多少PHP经验的前端人员(是的,没错就是我们这些Themer)来说很容易接受,不会有学习的障碍。另外,区块管理界面也可以让管理员很方便的管理和设置区块的输出位置。
然而,这也做有一些问题。首先,你的网站页面的布局依赖于Drupal后台的设置,虽然代码没有问题,但是如果有人做了某个误操作,把一个区块指定到了一个错误的区域中,那么,页面上渲染的元素就会出现在错误的地方。其次,区域和区块的嵌套,也会增加页面代码的冗余度——而这一点是大家反反复复提到的问题——Drupal输出的DIV实在太多了。
好在,Drupal的强大之处在于,大部分的情况下,你想做的事情都会有好几种方式,对于熟悉Drupal的人来说,可以根据自己的需要和喜好来选择。下面,我们要说的这种方式,可以让你跳过区域,直接把区块输出到页面上。如果你是一个刚入门的新手,你应该先看第4章的内容,先把几个主要的模版文件和区域、变量的输出方式搞清楚,然后在你遇到实际项目需要你在页面或者node中输出一个区块的时候,再来看这个部分。
这是一个古老的方法,10年前就有了,详情见D.O API及代码片段说明。
其中第一个参数module_name,是模块的机读名字,这里是block,第2个参数block_view,是钩子,这里是block_view,第三个参数block_delta,是传递给钩子函数的,这里是区块的delta。