作者:结一
众所周知,drupal的html结构是比较冗重的,而为了很好的标记这些结构就必然要给它们赋予相应的class,这样才能通过不同的或相同的class来赋予样式,完成这界面美观设计的飞跃。总的说来drupal的class只有比标签结构更多,很显然一个标签上可以挂好几个class呢,这么多的class必然有其生成的一些规律,所以本篇文章打算从这个角度来简单分析下drupal主题。
body的class
对于下面这段代码,相信大家都不会陌生
<body class="html front not-logged-in one-sidebar sidebar-second page-node">
...
</body>
为了了解它,我们找到modules/system目录下的html.tpl.php文件,打开找到第55行,发现如下代码,原来是由$classes变量输出的
<body class="<?php print $classes; ?>" <?php print $attributes;?>>
接下里我们在上面的注释部分的第36,37行找到如下说明
* - $classes String of classes that can be used to style contextually through * CSS.
这里只说明了原来是个数组而已,那到底怎么定义的呢,继续找到第39-41行,如下代码:
* @see template_preprocess() * @see template_preprocess_html() * @see template_process()
这就相当于如果要查看更多的话,就找到这三个函数。于是我们找到万能的drupal api 查询,一查原来在theme.inc文件的第2343行,找到这个之后,直接就可以在这个文件再搜其他两个函数了。

下面我们挑重要的分析下:
template_preprocess()函数中定义了变量classes_array为数组(第2357行)
// Initialize html class attribute for the current hook. $variables['classes_array'] = array(drupal_html_class($hook));
template_preprocess_html()函数中往数组classes_array中添加了一些元素(第2453-2489行),代码太多就不贴出来了,主要就是是否登录,是否首页,布局,page node,node type几个class
template_process()函数中把数组classes_array转成了以空格隔开的字符串,并赋值给变量$classes
// Flatten out classes.
$variables['classes'] = implode(' ', $variables['classes_array']);
这就是body class的整个一个流程。
如果要添删改呢,那么就得用到hook_preprocess_html(&$variables, $hook)这个函数了,以dgd7主题的template一个修改为例(第93行):
// In template_preprocess_html() we have easy access to the "class" attribute
// for the <body> element. Here we add a helper class that indicates that
// there is no title for the page to help styling the content region easily.
if (!drupal_get_title()) {
$vars['classes_array'][] = 'no-title';
}
region的class
因为page.tpl.php没有,所以我们直接跳过,然后同样该在modules/system目录找到region.tpl.php文件,注释的第9-14行说明了这个$class变量,而第32行调用了该变量,默认该变量有两个class,一个为region,一个为region-[name],至于怎么定义的可以在template_preprocess_region()函数中找到
* - $classes: String of classes that can be used to style contextually through * CSS. It can be manipulated through the variable $classes_array from * preprocess functions. The default values can be one or more of the following: * - region: The current template type, i.e., "theming hook". * - region-[name]: The name of the region with underscores replaced with * dashes. For example, the page_top region would have a region-page-top class. <div class="<?php print $classes; ?>">
如需增删改,使用hook_preprocess_region(),同样以dgd7主题的template为例,第98-113行:
/**
* Implements template_preprocess_region().
*
* The changes made in this function affect the variables for the region.tpl.php
* template file. In this theme we have not overridden this template, so the
* core default, located in modules/system/region.tpl.php isbeing used. This
* code is covered on pages 318-319.
*/
function dgd7_preprocess_region(&$vars) {
$region = $vars['region'];
// Add an "outer" class to the darker regions.
if (in_array($region, array('header', 'footer', 'sidebar_first', 'sidebar_second'))) {
$vars['classes_array'][] = 'outer';
}
}
node的class
在modules/node目录找到node.tpl.php,第21-35行解释了$class变量,而第83行调用该变量,如何定义可以查阅template_preprocess_node()函数,至于增删改,使用hook_preprocess_node()即可,是不是感觉突然一下简单了。
field的class
在modules/field/theme目录找到field.tpl.php,第21-35行解释了$class变量,而第53行调用该变量,如何定义可以查阅template_preprocess_field()函数,至于怎么...(省略,大家都懂的),这里提醒下,因为可能一个字段有多个值,所以这里使用了一层嵌套,先是field-items然后才是循环field-item,所以如果你想省标签的话,可以先判断$items数组的长度,如果只是一个,那么就直接干掉外层的field-items
<div class="field-items"<?php print $content_attributes; ?>>
<?php foreach ($items as $delta => $item): ?>
<div class="field-item <?php print $delta % 2 ? 'odd' : 'even'; ?>"<?php print $item_attributes[$delta]; ?>><?php print render($item); ?></div>
<?php endforeach; ?>
</div>
views的class
下载views模块,解压后在其theme目录中找到views-view.tpl.php,第8-15行解释再加第17行自定义的class,第30行调用,在目录的theme.inc中第44行template_preprocess_views_view()函数中定义如下(第55-68行):
// Basic classes
$vars['css_class'] = '';
$vars['classes_array'] = array();
$vars['classes_array'][] = 'view';
$vars['classes_array'][] = 'view-' . drupal_clean_css_identifier($vars['name']);
$vars['classes_array'][] = 'view-id-' . $vars['name'];
$vars['classes_array'][] = 'view-display-id-' . $vars['display_id'];
$css_class = $view->display_handler->get_option('css_class');
if (!empty($css_class)) {
$vars['css_class'] = preg_replace('/[^a-zA-Z0-9- ]/', '-', $css_class);
$vars['classes_array'][] = $vars['css_class'];
}
关于drupal的class机制就分析道这里,了解了这些class之后,对于美化主题选用class还是很有帮助的,不然那么多个class,依靠直觉去选一个那中奖的几率估计是比较高的。当然还有一个panels的,因为对这个没有什么研究,所以就不献丑了,喜欢的同学可以研究下,反正都是一个路子。
为数不多有启发的贴子,通俗易懂。。点32个赞
为数不多有启发的贴子,通俗易懂。。点32个赞
panels 迟早要研究