现在回到首页,发现有了内容,不过这里的区块标题不是我们想要的:
我们在输入区块标题,区块描述的时候,两个地方都输入了。区块标题默认会显示出来的。有人可能会问,区块描述为什么是必填的?而区块标题则允许为空?
区块标题,是在页面上面显示出来的区块的标题,区块描述是在后台显示给管理员看的,一个是给普通用户看的,一个是给管理员看的。
在区块的配置页面,我们将区块标题置为空,就可以解决这个问题了。还有一个办法,就是在区块的模板文件里面,不输出区块标题变量。
我们这里顺带讲解一下hook_theme和theme_hook之间的区别。在Drupal7下,所有的主题函数,又被称为主题钩子函数,比如
theme_breadcrumb
theme_links
theme_menu_tree
这些函数,属于theme_hook的范畴,theme_后面跟的是具体的钩子。
hook_theme,我们举个例子,比如node_theme(),block_theme,这是它在节点、区块里面的具体实现,它是一个普通的钩子函数,和我们平时所用的hook_form_alter是一个概念,这个钩子函数是用来注册主题函数和模板文件的。在Drupal中使用的主题函数和模板文件都需要在这里注册一下,不然的话Drupal无法识别这些主题函数或者模板文件。
我们向template.php文件中添加以下代码:
function snt_menu_tree__main_menu($variables) {
return '<ul>' . $variables['tree'] . '</ul>';
}
注意我们这里的函数名字,我们是可以使用snt_menu_tree,不过这将作用于所有的菜单,我们只想作用于主菜单,所以在后面加了__main_menu,这是主题函数建议,和模板建议是一个概念。
对于模板建议,我们知道,模板建议规则,是在模板文件的预处理函数中,通过'theme_hook_suggestions'定义的。很多人可能会问,主题函数的建议,是在什么地方定义的?在Drupal6的时候,主题函数是没有建议这么一说的,只有模板建议,在Drupal7下面改进了一下,增加了主题函数的建议,不是每个主题函数都支持建议的,需要具体情况具体分析,这取决于不断地实践。对于theme_menu_tree,我们在menu_tree_output函数里面,代码的最后部分:
// Add the theme wrapper for outer markup.
// Allow menu-specific theme overrides.
$build['#theme_wrappers'][] = 'menu_tree__' . strtr($data['link']['menu_name'], '-', '_');
theme_menu_tree的建议规则,就是在这里定义的,所以我们可以使用snt_menu_tree__main_menu这个函数,它只作用于主菜单。
现在清除缓存,访问首页,通过Firebug查看源代码:
ul标签上面的class属性已经被我们删除了,不过主导航的样式,还没有调整过来。我们现在覆写theme_menu_link,将这个函数从menu.inc中,复制到template.php中,我们来看一下默认的样子:
function theme_menu_link(array $variables) {
$element = $variables['element'];
$sub_menu = '';
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
$output = l($element['#title'], $element['#href'], $element['#localized_options']);
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
我们对它做相应的调整,这是调整后的代码:
function snt_menu_link__main_menu(array $variables) {
$element = $variables['element'];
$sub_menu = '';
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
$output = l('<span>'.$element['#title'].'</span>', $element['#href'], array('html' => TRUE,));
return '<li>' . $output . $sub_menu . "</li>\n";
}
这里面有两处修改,首先是将函数名字改为了snt_menu_link__main_menu,这里面的__main_menu,和前面我们用的,一样,都是主题函数建议;其次,就是将li里面的属性输出,给删除了。
可能还会有人问,我是怎么知道这个主题函数的建议规则的?在menu_tree_output函数里面,中间部分,有这样两行代码:
// Allow menu-specific theme overrides.
$element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_');
这里定义了theme_menu_link的建议规则。
现在清除缓存,查看源代码,和目标输出已经完全一致了:
当然,此时的样式,也正常了:
对于下面的友情链接,我们也可以将它改造为菜单的形式,覆写的办法和这里一样,我们这里采用静态区块的形式就可以了。
我们将modules\block下面的block.tpl.php复制到sites\all\themes\snt\templates目录下面,同时我们将代码里面区块标题的输出给注释掉,这是调整后的代码:
<div id="<?php print $block_html_id; ?>" class="<?php print $classes; ?>"<?php print $attributes; ?>>
<?php print render($title_prefix); ?>
<?php if ($block->subject): ?>
<h2<?php print $title_attributes; ?>><?php //print $block->subject ?></h2>
<?php endif;?>
<?php print render($title_suffix); ?>
<div class="content"<?php print $content_attributes; ?>>
<?php print $content ?>
</div>
</div>
清除缓存数据,现在所有的区块标题,都不见了。
我们现在继续,我们看到图片的显示不正常,如图所示:
这是因为图片的路径不对,这是我们使用的html片段:
<img src="images/br.gif" width="253" height="8" />
<img src="images/snt.gif" width="217" height="26" />
<img src="images/xiazai.gif" width="222" height="76" />
我们现在需要将它们调整为这样的形式:
<img src="http://localhost/snt2/sites/all/themes/snt/images/br.gif" width="253" height="8" />
<img src="http://localhost/snt2/sites/all/themes/snt/images/snt.gif" width="217" height="26" />
<img src="http://localhost/snt2/sites/all/themes/snt/images/xiazai.gif" width="222" height="76" />
这是可以工作的,但是,如果我们这样将路径写死在里面的话,将来如果我们更换了域名,此时需要重新的调整这些地址,如果要调整的地方很多,也是非常费力的。
我们可以采用这样的方案,启用核心自带的PHP过滤器模块,在banner-right区块里面,将对应的代码修改为:
<img src="<?php print base_path() . path_to_theme(); ?>/images/br.gif" width="253" height="8" />
<img src="<?php print base_path() . path_to_theme(); ?>/images/snt.gif" width="217" height="26" />
<img src="<?php print base_path() . path_to_theme(); ?>/images/xiazai.gif" width="222" height="76" />
然后将区块正文的文本格式设置为PHP Code,保存。图片的显示就正常了:
注意这里面,这段代码的使用,<?php print base_path() . path_to_theme(); ?>,这是在主题制作、Drupal开发中经常使用的代码。
对于页脚的snt-left区块,我们也做类似的调整:
<img src="<?php print base_path() . path_to_theme(); ?>/images/snt2.gif" width="66" height="25" />
现在的主导航区块,还是静态的,如图所示:
我们想使用Drupal的主菜单来管理这里的内容,这样更方便一点。
我们导航到admin/structure/menu,在这里找到主菜单,进入它的菜单链接列表页面admin/structure/menu/manage/main-menu。
我们对默认的Home菜单链接进行编辑,将“Home”修改为“首页”,保存。然后依次添加菜单链接:下载、充值、我的账户、业务支持、新手指引。我们知道,在创建菜单链接的时候,必须提供一个有效的路径,所以我们为这些菜单链接默认使用路径“node/1”,这里面只有一个例外,就是“我的账户”,我们为它使用了路径“user”。开始的时候,我们可以随便的指定一个路径,在项目的后期,当我们有了真实可用的路径以后,我们再将它修改过来。通过拖拽,我们调整一下菜单链接之间的相对位置,这是调整后的样子。
现在导航到区块管理界面admin/structure/block,找到主菜单区块,我们将它放到Navigation区域,然后将原来的nav区块的区域设置为None,这样我们就使用了主菜单做我们的导航了。调整完了以后,记得点击下面的保存区块按钮。
我们现在访问首页,来观察一下这个导航样式的变化,这是我在Firefox下面看到的效果:
我们看到样式变了,我们可以通过调整CSS,调整成原来的样子,我们也可以覆写HTML输出,让Drupal的HTML输出和美工切图后的HTML保持一致,这里我们采用后者。
这是当前的HTML,我们看到,与美工所给的HTML相比,Drupal输出了太多我们不想要的HTML markup。我们现在逐个的去掉这些多余的输出。
我们在firefox下面打开美工所给的静态页面,通过Firebug查看对应部分的源代码:
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们的目标就是覆写Drupal的输出,使其与美工所给的输出保持一致。我们首先来看最外面的<div class="region region-nav">,这个div是在region.tpl.php里面输出的。我们首先找到默认的region.tpl.php文件,它位于modules\system目录下面,我们将它复制到sites\all\themes\snt\templates目录下面。我们来看一下这个模板文件:
<?php if ($content): ?>
<div class="<?php print $classes; ?>">
<?php print $content; ?>
</div>
<?php endif; ?>
我们这里只需要修改这个模板文件里面的内容,将div标签给删除即可,如果这样做的话,所有区域的div标签都会被删除,我们这里不这样做,首先完整的保留这个模板文件,然后我们新建一个模板建议文件,专门用于这里的导航区域。
我们在sites\all\themes\snt\templates下面新建一个文件夹override,里面用来放置模板建议文件,然后在这个文件夹下面,再创建一个子文件夹region,用来放置region.tpl.php的模板建议。
首先,这里除了templates的文件夹名字是固定的以外,里面子文件夹的名字,可以随便起,Drupal会自动的遍历templates里面的所有文件、文件夹、子文件夹。当然,我们需要起一个含义明确的名字,如果我们把所有的模板文件、模板建议文件,都直接放到sites\all\themes\snt\templates下面,这也是可以的;不过我们在实际的项目中,需要覆写的模板文件比较多,为了管理的方便,我们将模板建议文件统一放在了override下面;在override下面,又新建若干个文件夹,分别放置对应模板文件的覆写。
我们通过Google搜索一下预处理函数template_preprocess_region,我们可以在region.tpl.php模板文件中的注释里面找到这个函数名字。通常在搜索结果的第一条,就指向了api.drupal.org上面的对应代码了,我们点击对应的链接。
来看一下这个函数:
function template_preprocess_region(&$variables) {
// Create the $content variable that templates expect.
$variables['content'] = $variables['elements']['#children'];
$variables['region'] = $variables['elements']['#region'];
$variables['classes_array'][] = drupal_region_class($variables['region']);
$variables['theme_hook_suggestions'][] = 'region__' . $variables['region'];
}
注意代码里面的最后一行,表示它支持region--[region_name].tpl.php形式的模板建议。代码里面使用的是下划线,文件名字里面使用的是连字符。我们这里区域的名字,就是nav,这是在主题的snt.info文件中定义的。所以我们只需要创建region--nav.tpl.php就可以了。对于熟悉Drupal6主题开发的读者,这里需要注意,这里面是两个连字符--,不是一个,这是Drupal7与Drupal6之间的一个区别。
我们将region.tpl.php复制到sites\all\themes\snt\templates\override\region,然后将它重命名为region--nav.tpl.php,最后打开region--nav.tpl.php,删除里面的div代码,这是删除后的样子:
<?php if ($content): ?>
<?php print $content; ?>
<?php endif; ?>
其实这里面的if语句,在我们这里也没有什么特别的用出了,因此把if语句,也删除掉,这是删除后的代码:
<?php print $content; ?>
现在清除缓存,在浏览器中打开新标签页,访问http://localhost/snt2/,使用firebug查看页面源代码。我们看到,我们去掉region相关的<div>了。
但是此时,样式还没有任何变化。我们继续前进,我们把区块里面的多余HTML标签给删除掉。
我们在sites\all\themes\snt\templates\override下面创建一个文件夹block,将sites\all\themes\snt\templates里面的block.tpl.php复制过来。我们打开block.tpl.php,在注释里面找到函数template_preprocess_block,通过Google搜索这个函数,点击打开api.drupal.org上面的链接,找到该函数的代码,我们看这一部分:
这里的英文注视,说的就是下划线、连字符两者的用法,我们在模块的代码里面,也就是这里的预处理函书中,使用下划线,在文件名字里面使用连字符。如果在代码的'theme_hook_suggestions'数组里面使用了连字符,它就不会正常工作。我们看到,block.tpl.php支持以下形式的模板建议:
block--[region].tpl.php
block--[module].tpl.php
block--[module]--[delta].tpl.php
注意,这里需要解释一下的是这里的delta,delta是区块在当前模块里面的唯一标识,它在当前模块里面是唯一的,但是不是在所有区块里面都是唯一的。所以模块名,加上delta,合在一起,就是区块的唯一ID。
在我们这里,使用的区域为nav,模块名为system,delta为main-menu。我们导航到区块的管理界面,点击配置链接,进入区块的配置页面。此时的配置链接里面,就包含模块名和Delta信息:admin/structure/block/manage/system/main-menu/configure。
因此我们可以使用:
block--nav.tpl.php
block--system--main-menu.tpl.php
我们这里采用后者,将sites\all\themes\snt\templates\override\block下面的block.tpl.php重命名为block--system--main-menu.tpl.php,然后修改模板文件里面的代码,这是修改后的:
<?php print $content ?>
是的,就是这样,除了区块内容以外,我们没有输出任何的东西。这是我在实际的项目中,经常采用的方法。但是这种方式也有一种局限性,就是说,区块的配置链接没有了,所以当你使用的时候,需要注意一下,到底要不要输出区块的配置链接。区块的配置链接,是通过变量$title_suffix输出的。
我们现在清除缓存,使用Firebug查看源代码,现在干净了很多:
不过样式还没有没有变化:
与美工所给的输出相比的,我们的ul、li上面多了class属性,我们来看ul,Drupal默认的输出为<ul class="menu">,为了和美工所给的HTML保持一致,我们需要将它覆写为<ul>。在哪个模板文件里面覆写这里的输出呢?实际上这里的HTML是由Drupal的菜单系统控制,而且是由主题函数控制的。
打开Drupal核心的includes文件夹,在里面找到menu.inc文件,打开这个文件,在这里面可以找到函数theme_menu_tree和theme_menu_link,这两个主题函数用来控制菜单和菜单链接的HTML输出。我们需要对这两个函数进行覆写。
首先来看theme_menu_tree,代码如下:
function theme_menu_tree($variables) {
return '<ul class="menu">' . $variables['tree'] . '</ul>';
}
这里的class="menu",就是我们想要去除的。
我们回到sites\all\themes\snt文件夹下,在这里面创建文件template.php,这里的template.php,就相当于模块的.module文件,它对于Drupal的主题是非常重要的。我们在template.php文件中,可以做很多事情,比如:
1) 自定义函数,可以放到这里,然后在模板文件中调用,这样模板文件中,就不用放置太多的PHP逻辑代码。
2) 实现预处理、处理函数,为模板文件添加变量或者修改变量。
3) 实现钩子函数,比如hook_form_alter,hook_theme,在这一点上完全等同于.module文件,这是Drupal7对Drupal6的一个改进。
4) 实现主题函数,在当前主题下覆写默认的输出。
我们这里,当前用到的是第4条,实现主题函数的覆写。对于创建template.php文件,我仍然是喜欢复制一个已有的文件,然后修改。我这里是从网上书店里面复制过来的,里面包含了很多注释掉的代码。