drupal的PHPTemplate主题引擎

PHPTemplate是由Adrian Rossouw编写的一个drupal主题引擎,Adrian Rossouw还是Drupal 4.5主题改革的幕后推动者。

它使用something.tpl.php模板文件来实现Drupal的theme_something()函数的功能。Drupal的主题化函数文档可参看Development Plumbing站点。每个模板文件都包含了一个HTML骨架,里面嵌入了一些简单的PHP语句,用来输出动态数据。因此,如果你仅仅了解一点PHP的话,那么PHPTemplate应该是你的很好的选择:使用一些基本的PHP代码片断,你可以很容易的创建高级的drupal主题

如果你不了解PHP的话,那么PHPTemplate仍然是一个很好的选择,因为这里面仅涉及到了很少的代码,而且这些代码都是一个模式的。你可以复制粘贴这些代码就可以了。

一个扩展的论坛讨论提供了创建PHPTemplate背后的原因。

 

提示:输出可用的变量

输出变量数组

<?php
print '<pre>';
print_r(get_defined_vars());
print '</pre>';
?>

 

使用HTML标记输出变量数组

<?php
print '<pre>';
print htmlspecialchars(print_r(get_defined_vars(), TRUE), ENT_QUOTES);
print '</pre>';
?>

 

 相关联接:http://drupal.org/phptemplate , Think in Drupal

创建一个新的drupal PHPTemplate主题

为了创建一个新的PHPTemplate主题,你需要在你的themes目录下,创建一个新的目录,例如themes/mytheme.接着,你需要在该目录下创建一个名为page.tpl.php的文件.或者你也可以拷贝一个已有主题,仅仅改一下名字.对于Drupal 5,你可以基于Zen 或者Blue breeze来构建自己的主题.

 

page.tpl.php是唯一的一个必须的文件.它将覆写theme('page')函数,用来输出页面的最终内容,包括各种修饰,比如页首、标签、面包屑、左右栏、和页脚等等。

You can create files to override the following functions:

你可以创建模板文件来覆写下面的函数

 

 

Themes/engines/phptemplate下面包含了这些模板文件的样板,对于page.tpl.php的例子可参看box_grey。简单的将这些模板文件拷贝到你的theme/mytheme目录下,然后编辑它们。注意,对于PHPTemplate主题,你需要通过访问administer > themes来刷新它的缓存,从而识别出新的.tpl.php模板文件。

如果你要覆写的drupal主题函数,在这里没有列出来的话,你需要自己提供一个覆写

 相关联接: http://drupal.org/node/11819 , Think in Drupal

Drupal版本:

drupal的Block.tpl.php

用于输出区块中(页面的左右栏)的内容.这个模板是可选的,通过拷贝默认的模板文件,并修改它,就可以覆写这个模板.

 

模板可用的变量

$block对象包括:

$block->module

生成该区块的模块的名称.

$block->delta

区块在其模块中的id.

$block->subject

区块标题.

$block->content

区块的html内容

$block->status

区块的状态(0或者1).

$block->region

区域名称,默认可用的区域有'left', 'right', 'header' 和'footer'(左栏,右栏,页首,页脚).

$block->throttle:

节流阀设置.

 

其它变量:

$directory

主题所在的目录,比如themes/garland 或者themes/garland/minelli.

$is_front

如果当前页面为drupal站点首页的话,返回True。

$id

展示的区块的序列id,比如,第一个区块为1,第2个区块为2,等等。

$block_id

与$id一样,但是在左右栏中将被重置。

$zebra

'odd' 或者'even'。这对于使用css创建斑马线非常有用。

$block_zebra

与$zebra一样,但是在左右栏中将被重置。

 

默认模板

默认的block.tpl.php,位于themes/engines/phptemplate/block.tpl.php。

 

<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="block block-<?php print $block->module ?>">

<?php if ($block->subject): ?>
  <h2><?php print $block->subject ?></h2>
<?php endif;?>

  <div class="content"><?php print $block->content ?></div>
</div>

 

 

Drupal 4.6 vs. Drupal 4.7及更高版本

在Drupal 4.6中这些变量是不同的:

  • $block->region只允许使用0(左栏)或者1(右栏)。
  • 使用$seqid代替$id。
  • 使用$block_seqid代替$block_id。

在drupal4.7及更高的版本中,除了默认的'left', 'right', 'header' 和'footer'以外,你还可以定义自己的区域。

推荐阅读:

 

 相关链接: http://drupal.org/node/11813 , Think in Drupal

 

添加一个“编辑这个区块”链接

我为客户创建过一些drupal站点,站点创建后由客户来维护,我发现客户对于节点、页面、区块这些drupal概念非常困惑,所以我在所有的自定义区块的底部都添加了一个链接“编辑这个区块”,而只有具有区块管理权限的用户才可以看到这个链接(同样,我对page.tpl.php也作了相应的修改,使得只有具有页面管理权限的用户才能看到页面右下角的编辑链接)。

 

<div class="<?php print "block block-$block->module" ?>" id="<?php print "block-$block->module-$block->delta"; ?>">
<?php print $block->subject ?>
  <div class="content"><?php print $block->content ?>
  <?php  if ($block->module == "block"):?>
      <?php  if (user_access('administer blocks')) :?>
      <br /><center><a href='/admin/block/edit/<?php print $block->delta;?>'>(edit this block)</a></center>
      <?php endif; ?>
  <?php endif; ?>
  </div>
</div>

 

注意编辑链接的路径在各个drupal版本下有所不同。

  • /admin/build/block/configure 用于drupal5.x
  • /admin/block/configure 用于drupal4.7
  • /admin/block/edit/ 用于drupal4.6

 相关链接: http://drupal.org/node/120334, Think in Drupal

按区域或者模块,对drupal区块进行主题化

在Drupal5.0中,设计者可以基于特定的区块、区块所属的模块、以及区块所在的区域,为区块创建多个tpl.php文件。

 

drupal模板文件的查找顺序如下:

  • block-[module]-[delta].tpl.php
  • block-[module].tpl.php
  • block-[region].tpl.php
  • block.tpl.php

 

例如,用户登录区块的delta为0。假如你将它放在了左栏中,当它显示时,PHPTemplate将按照下面的顺序寻找模板文件:

  • block-user-0.tpl.php
  • block-user.tpl.php
  • block-left.tpl.php
  • block.tpl.php

 

通过查看页面的源文件,你可以找到区块所属的模块以及delta:每个区块的主DIV都使用了下面的类和ID:

<div class="block block-{module}" id="block-{module}-{delta}"> 

 

 

使用CSS自定义样式

你也可以使用这些类和IDs为区块添加CSS规则,可用于所有的区块,特定模块的区块,或者单个区块。(为了通过区域来自定义区块的样式,你需要在选择器中使用整个区域DIV的类或者ID)。

注意,delta一般是一个数字:模块中区块的排序,从0开始。在一些情况下,delta也可以是一个名字:为了给Views模块创建的区块定义外观,你可以使用block-views-[name of your block].tpl.php。

 相关链接:http://drupal.org/node/104319 , Think in Drupal

 

Drupal版本:

用于不同区块类型的可选模板(drupal4.7)

注意:在Drupal 5中,这更简单了。只需要像前文所讲的那样就可以了。

 

方法1

这里所讲的具有一些技巧性,它允许你为特定的区块创建一个单独的block.tpl.php模板。你可以使用区块名称或者区块ID进行控制。下面是一个修改后的block.tpl.php,在前面带了一个条件语句。你所要做的就是编辑module == '[模块名]' 和delta == '[区块名或id]'部分就可以了。

下面是我当前的block.tpl.php,条件里面的区块信息是我站点特有的。如果你想在你的drupal站点上使用它的话,你需要按照前面所说的对其进行修改。这个是在我的站点上,为两个区块加载一个自定义block.tpl.php,你可以根据需要用于,1个,6个等等。对于每个自定义模板,你都需要一个条件语句("if "部分)。

 

<?php
if ( ( $block->module == 'views' && $block->delta == 'Cool Block' ) || ( $block->module == 'node' && $block->delta == '0' ) ) {
    include 'block-custom.tpl.php'; /*load a custom template for those two block IDs */
    return; }
?>
<div class="<?php print "block block-$block->module" ?>" id="<?php print "block-$block->module-$block->delta"; ?>">
  <div class="title"><h3><?php print $block->subject ?></h3></div>
  <div class="content"><?php print $block->content ?></div>
</div>

你需要自己创建一个block-custom.tpl.php,根据需要你可以创建任意多个这样的模板文件。为了在你的Drupal站点上进行测试,你可以复制一份标准的区块模板,将其改名为block-custom.tpl.php,然后对其进行编辑,比如将标题放在最后面而不是最前面,然后查看效果。剩下的就是你的事儿了。你可以在模板中根据需要放置任何想要的东西。

这意味着所有的区块都可以拥有自定义的外观,这是很多人都热切希望的。将这个添加到新的区域功能中,你将拥有100%的自定义区块。

iDonny, nevetsHeine对本文作了审查

 

方法2

JohnAlbin写的

block.tpl.php的内容:

<?php
    $block_module = $block->module;
    // force delta to be alphanumeric
    $block_name = $block_module . '-' . preg_replace('/[^\w]/', '', $block->delta);
    switch ($block_name) {
        case 'menu-2':                // Primary links
        case 'views-CoolBlock':        // a custom Views block named "Cool Block"
            if ( @include("block-$block_name.tpl.php") ) {
                return;
            }
            break;
    }
?>

 

<div class="block block-<?php print $block_module; ?>" id="block-<?php print $block_name; ?>">
<h2 class="title"><?php print $block->subject; ?></h2>
<div class="content"><?php print $block->content; ?></div>
</div>

 

这段代码就有下面的优势:

1.       在id属性中不会有奇怪的字符(比如空格)。

2.       如果没有"block-[module]-[delta].tpl.php"文件的话,也不会引起PHP警告,此时将会使用默认的block.tpl.php代码。

 

方法3

dman写的

在block.tpl.php的最顶部:

<?php
    // allow for unique blocks to have their own phptemplate theme
    if(!empty($block->subject))
      $blockid = 'block-'.strtolower(preg_replace("/[^A-Za-z0-9]+/","-",$block->subject));
    else
      $blockid = 'block-'.$block->module.'-'.$block->delta;

    if (file_exists(path_to_theme() . "/$blockid.tpl.php")) {
      include path_to_theme() . "/$blockid.tpl.php";
      return;
    }
?>

现在你就可以实现block-block-7.tpl.php或者block-login.tpl.php等等模板文件了。

 相关链接:http://drupal.org/node/63757 , Think in Drupal

 

Drupal版本:

drupal Box.tpl.php

在一个页面元素周围输出一个简单的html盒子(box).唯一常用的例子是,在drupal的内核中的搜索结果和评论表单中用到了.在评论试图选项周围,就是用的box.tpl.php.

注意,这个模板很少用到,我专职的做过1年的drupal开发,从没有遇到过要修改这个模板的,它仅仅用于Drupal的内核中,除非你需要开发内核,否则你是不会需要修改这个模板的.

 

可用变量

$title

盒子的标题.

$content

盒子的内容.

$region

区域. Main(主), left(左) 或者 right(右).

 

默认模板

<div class="box">
  <h2><?php print $title ?></h2>
  <div class="content"><?php print $content ?></div>
</div>

 

相关链接: http://drupal.org/node/11814 , Think in Drupal

Drupal版本:

drupal Comment.tpl.php

定义一个评论区块所输出的HTML.没有对评论进行任何逻辑处理,仅仅用于输出实际的评论.

 

可用变量

$author

链接到作者的个人信息页面.

$comment (object)

评论对象,将传递给theme_comment函数.

$content

链接的内容.

$date

格式化的发布日期.

$directory

主题所在的目录,比如themes/garland or themes/garland/minelli.

$id

被展示评论的序列ID.

$is_front

如果当前页面为首页的话,返回true.

$links

位于评论下面的上下文链接.

$new

英文'new'的翻译文本,如果评论确实是新的,未读过的.

$picture

用户图片的HTML(包含<a>标签),如果展示被启用并且图片被设置了.

$submitted

翻译的发布信息字符串.

$title

链接到评论的标题上.

$zebra

斑马线,odd/even,二选一.

 

默认Drupal模板文件

 

<div class="comment<?php print ($comment->new) ? ' comment-new' : ''; print ($comment->status == COMMENT_NOT_PUBLISHED) ? ' comment-unpublished' : ''; ?> clear-block">
  <?php print $picture ?>

<?php if ($comment->new) : ?>
  <a id="new"></a>
  <span class="new"><?php print $new ?></span>
<?php endif; ?>

  <h3><?php print $title ?></h3>

  <div class="submitted">
    <?php print $submitted ?>
  </div>

  <div class="content">
    <?php print $content ?>
  </div>

  <?php print $links ?>
</div>

 

 相关链接:http://drupal.org/node/11815 , Think in Drupal

drupal的Node.tpl.php

这个模板文件控制着节点的输出,和节点摘要的输出.它仅能影响page.tpl.php中的$content变量。

 

可用变量

$content

节点内容,如果是摘要的话,就是节点的teaser。

$date

格式化的节点创建日期。

$directory

主题所在的目录,比如themes/garland or themes/garland/minelli。

$id

被展示节点,在列表中的序列ID。

$is_front

如果当前页面为首页的话,返回true。

$links

节点链接。

$main (drupal4.6)

如果节点出现在上下文中,比如首页,在这里只展示teaser,此时为true。在drupal4.7及以后版本中,不再使用这个变量了。

$name

格式化的作者名。

$node (object)

节点对象。为了查看当前节点对象的所有属性,将下面的代码放到你的node.tpl.php中:

<pre><?php print_r($node); ?></pre>

$node_url

指向节点的链接。

$page

如果节点单独展示在一个页面时,返回true。

$picture

如果启用的话,返回用户图片的HTML。

$sticky

如果节点是sticky(粘的)的话,返回true.

$submitted

如果为这个节点类型启用了节点信息的展示的话,它将包含作者和节点创建日期等信息。

$taxonomy (array)

一个展示分类术语的HTML链接数组。

$teaser

布尔值,用来指示是否需要返回teaser,而不是整个节点文本。

$terms

分类术语的HTML。

$title

节点标题

$zebra

斑马线,odd/even二选一。

 

提示:输出可用的变量。

输出变量数组:

<?php
print '<pre>';
print_r(get_defined_vars());
print '</pre>';
?>

 

输出带有HTML的变量数组:

<?php
print '<pre>';
print htmlspecialchars(print_r(get_defined_vars(), TRUE), ENT_QUOTES);
print '</pre>';
?>

 

Drupal5.x的默认模板文件

 

<div id="node-<?php print $node->nid; ?>" class="node<?php if ($sticky) { print ' sticky'; } ?><?php if (!$status) { print ' node-unpublished'; } ?> clear-block">

<?php print $picture ?>

<?php if ($page == 0): ?>
  <h2><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2>
<?php endif; ?>

  <div class="meta">
  <?php if ($submitted): ?>
    <span class="submitted"><?php print $submitted ?></span>
  <?php endif; ?>

  <?php if ($terms): ?>
    <span class="terms"><?php print $terms ?></span>
  <?php endif;?>
  </div>

  <div class="content">
    <?php print $content ?>
  </div>

<?php
  if ($links) {
    print $links;
  }
?>

</div>

 

 

Drupal4.7的默认模板文件

 

<div class="node<?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-unpublished"; } ?>">
  <?php if ($page == 0): ?>
    <h2><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2>
  <?php endif; ?>
  <?php print $picture ?>

  <div class="info"><?php print $submitted ?><span class="terms"><?php print $terms ?></span></div>
  <div class="content">
    <?php print $content ?>
  </div>
<?php if ($links): ?>

    <?php if ($picture): ?>
      <br class='clear' />
    <?php endif; ?>
    <div class="links"><?php print $links ?></div>
<?php endif; ?>
</div>

相关链接: http://drupal.org/node/11816 , Think in Drupal

drupal首页判断,用$page==0 还是 $is_front?

如果你打算使用$is_front来检查当前页面是不是展示的单个节点的话,这里有篇好的帖子(尤其是帖子下面的评论更值得一读),讨论了变量$page和$is_front的不同.

 

只有当你处在drupal站点的首页时,变量$is_front才被设置,也就是为真,而当你处在其它页面时,$is_front为假。对于普通的节点列表页面,比如当你点击一个drupal分类术语后所得到的节点列表页面,在这里$is_front就为假(false)。

 

对于所有的节点列表页面,包括特定的分类术语下面的节点列表页面,$page都等于0。

 

 相关链接: http://drupal.org/node/39891 , Think in Drupal

为特定节点使用单独的drupal主题模板

如果你想为一个drupal节点使用一个特定的node.tpl.php模板文件的话,你可以将下面的代码拷贝或者合并到你的template.php中:

<?php
function _phptemplate_variables($hook, $vars = array()) {
  switch ($hook) {
    case 'node':
      $vars['template_files'] = array('node-'. $vars['nid']);
      break;
  }
  return $vars;
}
?>

现在,比如对于节点34,你就可以专门为它创建一个主题,名为node-34.tpl.php的模板文件.

相关链接: http://drupal.org/node/136647 , Think in Drupal

 

 

Drupal版本:

drupal CCK节点类型的主题定制

       本文是基于我的实践经验所写,我的客户向我提出了一个要求,如何让CCK定义的节点类型拥有一个他想要的主题外观。当然,有多种方式可以实现这一点:1)仅用CSS(并不是所有情况下都有效);2)使用Contemplate模块,(是不是的会让我挠头);3)一个自定义模块(根据他的情况,也不是一个好办法);4)主题模板。

     随着他的需求的日益明确,我觉得主题模板模板应该是最好的办法。当然,这也是能够传授给他的最简单的方法。

具体要求和环境

       新的节点类型已经用CCK定义好了,当然它还可以更精简一些。节点类型的名字是“agency”。

       这个Drupal站点使用的主题为Garland。

       站长对于外观没有太明确的要求,她只是想让我给他一个简单的教程,这样将来他好自己修改。他熟悉CSS,也了解一点PHP。

 

解决方案

     首先,让我们看一下由CCK定义的节点类型。

在这个图片中,我们看到"Name"(名称)和 "Type"(类型);注意这些字段下面的说明:

  • Name – “用户可读的该节点类型的名字”
  • Type –“机器可读的该节点类型的名字”

   为了构建主题模板文件,我们需要"Type"。

      我们还需要注意,在这里我们把"body"字段叫作了什么。我们称它为"Description"。

      当我们来到"Manage fields"(管理字段集)页面时,我们看到上图所示的页面。其中,"Name"列是我们需要的。然而,这里需要注意一点:我们这里没有字段叫作"body filter",这是Drupal内核中的一个表单技术,将“body”名称为"body_filter".

      好了,现在全部信息我们都有了,让我们开始为这个节点类新定制主题。

 相关链接:http://drupal.org/node/266817 , Think in Drupal

Drupal版本:

drupal CCK节点类型的主题定制(1)

打开你的文本编辑器,新建一个文件。在这里,我们将使用HTML 和PHP。首先,先输入一些基本的东西,以供将来定义CSS时使用。

<div class="content agency">
</div>
<div class="clear-block clear"></div>

 

它的意思是说,“下面的是这个节点的内容,节点类型为'agency'”。这里我选择使用了机器可读的节点类型作为内容标识,你也可以使用自己的标识。"content"是Drupal的标准用法,所以你需要保留它。第2行仅仅是一个结束标签。第3行也不是必需的,但是由于我们的节点中包含了图片,图片的大小可能会有所不同,加上这一行,能让浏览器返回“起点处”,从而保持统一的外观。

 

那么,现在我假设你想输出一些实际的内容?

 

节点中包含了一个图片,这里我们用的是使用了ImageCache模块的CCK "Image"字段。我们想把图片放在左上方。实际上,如果把公司名(标题)放在图片上方的话,效果可能会好一些,至于标题和图片的位置问题,我们现在先不管它,首先要做的是将它们显示出来。我们将这些东西插入到第一个<div>标签中。

 

 

ImageCache模块提供了一个非常方便的主题函数,让我们来使用它。

[顺便说一句,'echo'函数比'print'函数稍微快一点,所以我使用'echo'。不过大多数主题制作者都使用'print'。两者都能工作。

]

<?php echo theme('imagecache', 'thumbnail', $node->field_logo[0]['filepath'], $node->title, $node->title, array('align' => 'left', 'hspace' => '10')); ?>

 

在这个函数中,首先使用"thumbnail"(可以改为你自己要用的)来设置图片的大小。对于数据字段("$node->field_logo[0]['filepath']"),我将在下面作出解释。接下来的两个"$node->title"参数,它是告诉函数,对于"alt" 和"title"属性,在这里都使用公司名称。最后,我们使用了一个数组,它告诉ImageCache向IMG标签中添加属性'align="left"' 和'hspace="10"'。

 

 

好了,我们把图片插进去了,现在轮到标题了。在Drupal中,最标准的做法是使用<h2>标签。这个取决于你的习惯,不过在这里我将遵循Drupal标准。整个节点对象在主题中都是可用的,按照Drupal标准的,它叫作"$node"。在节点对象内部的标题(在这种情况下,就是公司名称),它的叫法就有点奇怪了,叫做 "title",而不是“company_name”。因此我们可以使用"$node->title"来引用它。

<h2><?php echo l($node->title, 'node/'. $node->nid, array('title' => t('View agency')));?></h2>

 

另一个标准的Drupal做法是,在标题上加一个指向节点本身的链接,这样你就可以进入节点页面,如果有权限的话,可对其进行编辑。所以我在这里使用l()函数。关于这个函数的更多信息,可参看这里

在我的例子中,我使用表格(table)来对数据进行格式化。你也可以这样做,或者你也可以使用<div>+CSS。有些主题制作者就喜欢使用后者。你可以自由的选用你喜欢的技术。但一定要小心,不要与你的主题冲突了。

 

在我的例子中,我使用了CCK_Address模块,由于它与其它的CCK字段有点区别,所以我将讲解一下它的字段是怎么命名的。地址模块允许使用多个地址;多个地址构成一个名为"field_address"的数组,所以第一个地址是0,第2个地址是1,以此类推。这个模块还提供了几个子字段,它们的标签不需要与编辑页面的保持一致。比如,显示的"Address"字段,在内部为"street1";"Address continued"在内部为"street2";而"Apt/suite number"则简记为"apt."

 

我没有能够为这些字段使用"content_format"函数来格式化它们的内容。不知这是好是坏,但是它能工作。而普通的CCK字段有一个安全的"view"元素可用。

 

<tr><th>Address</th><td>
<?php
  echo $node->field_address[0]['street1'];
  if ($node->field_address[0]['apt']) { echo '; '. $node->field_address[0]['apt']; }
  if ($node->field_address[0]['street2']) { echo '<br/>'. $node->field_address[0]['street2']; }
  echo '<br/>'. $node->field_address[0]['city'] .', '. $node->field_address[0]['state'] .' '. $node->field_address[0]['zip'];
  if ($node->field_address[0]['country'] != 'US') { echo '<br/><big>'. $node->field_address[0]['country'] .'</big>'; }
?>
</td></tr>

 

注意,我这里加了一点逻辑,从而将城市,州,和邮政编码连在一起(采用美国的格式)。由于我就在美国,所以也没有显示"US",如果加上这个的话,这里的邮递员会觉得别扭的。

 

现在,除了"body"字段(也就是这里的"description")以外,到目前为止,所遇到的所有字段的处理方式都是一样的。如果你参考一下你的“管理字段集”("manage fields")页面的字段名称,现在仅有几点需要你了解。

 

和前面的"address"一样,CCK所有字段可以是单独的,也可以是多个的,所以需要使用数足来管理它们,数组名就为“管理字段集”页面的字段名。例如,我们把电话号码定义为"field_agency_telephone",这个和前面的一样,第一个元素为field_agency_telephone[0],第2个元素为field_agency_telephone[1],以此类推。在我们这种情况下,不需要多个电话号码,如果需要的话,使用一个简单的"foreach"循环就可以做到了。

CCK提供了一个内容格式化工具(content formatter),但是你用不到它。每一个字段数组,都有一个‘view’,这个就是内容格式化工具生成的,但它已经为你做好了。这是展示数据的安全方式。而对于电子邮件地址和超链接等字段内容,CCK已经对其进行了正确的格式化处理。

 

让我们归者一下,引用一个字段的最好的方式就是"$field_name[0]['view'],"其中field_name可从“管理字段集”页面找到。

<tr><th>Phone</th><td><?php echo $node->field_phone[0]['view'];?></td></tr>
<tr><th>Email</th><td><?php echo $node->field_email[0]['view'];?></td></tr>
<tr><th>Web site</th><td><?php echo $node->field_website[0]['view'];?></td></tr>

 

那么,现在基本上就快完工了;现在就剩下"description"(或者body)字段需要考虑了。这个与前面所讲的不一样,所以你必须要小心一点。这个字段是这样引用的,"$node->content['body']['#value']",我看到一些人在帖子中建议,"$node->description"也应该可以工作,但是现在还不能。

 

那么,让我们将整个例子正合到一起,希望我的讲解还算清晰明了:

<div class="content agency">
<?php echo theme('imagecache', 'thumbnail', $node->field_logo[0]['filepath'], $node->title, $node->title, array('align' => 'left', 'hspace' => '10')); ?>
<h2><big><?php echo l($node->title, 'node/'. $node->nid, array('title' => t('View agency')));?></big></h2><br/>
<table border="2" cellpadding="5">
<tr><th>Address</th><td>
<?php
  echo $node->field_address[0]['street1'];
  if ($node->field_address[0]['apt']) { echo '; '. $node->field_address[0]['apt']; }
  if ($node->field_address[0]['street2']) { echo '<br/>'. $node->field_address[0]['street2']; }
  echo '<br/>'. $node->field_address[0]['city'] .', '. $node->field_address[0]['state'] .' '. $node->field_address[0]['zip'];
  if ($node->field_address[0]['country'] != 'US') { echo '<br/><big>'. $node->field_address[0]['country'] .'</big>'; }
?>
</td></tr>
<tr><th>Phone</th><td><?php echo $node->field_phone[0]['view'];?></td></tr>
<tr><th>Email</th><td><?php echo $node->field_email[0]['view'];?></td></tr>
<tr><th>Web site</th><td><?php echo $node->field_website[0]['view'];?></td></tr>
</table>
<?php
  if ($node->content['body']['#value']) {
      echo '<p><big>'. $node->content['body']['#value'] .'</big></p>';
  }
?>
</div>
<div class="clear-block clear"></div>

 

While I initially developed this on the Bluemarine theme, it worked without change on the Garland theme, except I needed one small addition to my CSS: ".agency table {width: auto;}". This is because the Garland theme has the annoying habit of ignoring my "width" attributes and forcing 100%.

这个模板文件,我最初是在Bluemarine主题下面开发的,当我把它放在Garland主题下时,只需要在我的CSS中加入".agency table {width: auto;}"就可以了。其它都不用修改。这是由于Garland主题忽略了我的"width"属性,并将其强制为100%的缘故。

 

最后…

现在将你的工作保存,并检查它是否正常工作。

将文件保存到你主题的文件夹下,取名为"node-content_type.tpl.php",其中content_type是你在第一步中给节点类型起的内部名字。

 

展示一列节点

站点已经安装了Views模块,这样我就可以使用这个模块来选择资源了,尽管我觉得这样运行效率低一些。

 由于所有字段在主题中都列出来了,那么我在Views中需要做些什么呢?对于"teaser view",我发现所有要做的就是选择节点中的字段,比如标题等等,然后你就得到了想要的节点。你可能还想排个序,但是这已经不是本文讨论的范围了。

 

 相关链接: http://drupal.org/node/266817 , Think in Drupal

Drupal版本:

根据drupal节点类型对节点进行主题化

模板文件node.tpl.php适用于所有类型的节点的主题化.这个文件覆盖了所有的节点类型,你可以按照手册的node.tpl.php页面的说明,对这个文件进行修改.为了对单独的节点类型分别进行主题化,你需要在你的主题文件夹下面创建一个node-$type.tpl.php文件,其中$type是节点类型的名称,从而为每种类型按照需要自定义主题.一些例子:

 

  • node-story.tpl.php 仅用于story节点的主题化
  • node-page.tpl.php 仅用于page节点的主题化(注意,这个与page.tpl.php的区别,后者是用来控制整个页面的输出的,包括页首,左右栏等等)
  • node- forum.tpl.php 仅用于forum节点的主题化
  • node- book.tpl.php 仅用于book节点的主题化

 

在一般情况下,你可以将$type替换为任何节点类型的名称.一种特殊情况是, flexinode模块,它在内部使用数字对类型进行命名. Flexinodes的主题化可参看http://drupal.org/node/31646.还有,你也不能使用 node-admin.tpl.php仅仅对管理页面进行主题化.(译者注:实际上,是可以这样用的,但是你需要加点东西,在template.php中加个函数,但是这种用法不常见,文中所讲的应该是,不能直接这样用.)

创建了这个文件以后,将node.tpl.php的内容拷贝进取,然后按照要求进行修改. node.tpl.php列出的所有变量都可以使用.当Drupal展示该类型的节点时,就会使用你新创建的模板文件来代替默认的node.tpl.php.

为特定的flexinode类型创建一个drupal主题

对于由flexinode创建的节点类型,你给节点类型的命名(也就是展示的节点类型名)与系统内部使用的节点类型名不一样.在系统内部使用的节点类型名为"flexinode-1", "flexinode-2",等等.查看节点类型名的一种方式是,直接查看数据库表“node”的name列。

例如,如果你使用flexinode创建了一个名为"info"的节点类型,如果你查看数据库的话,你就会发现其内部名称为"flexinode-1"。所以,你为"info"创建的模板文件应该命名为"node-flexinode-1.tpl.php"。

 

 

你也可以通过访问admin>>content>>content types页面,点击所选的节点类型,来查看flexinode后面的数字。这个数字将出现在url(比如,node/types/edit_type/1就意味着flexinode-1)。

 

在你的节点模板中(比如node-flexinode-1.tpl.php),你可以这样引用flexinode的不同字段:

<?php print $node->flexinode_1 ?>

 

导航到admin>>content>>content types页面,点击编辑所选字段链接,查看相应的url(比如node/type/edit_field/1,就意味着$node->flexinode_1),你会发现不同的字段的引用方式是类似的。

 

这种方式适用于文本输入框,文本字段,日期/时间。对于图片你可以这样:
<img src="/<?php print $node->flexinode_1->filepath ?>" />.

 

如果需要输出对象的话,你需要研究一下代码了。你可以使用下面的输出命令:

<?php print serialize($node->flexinode_1)?>

它看起来有点怪,但它是一序列的变量和它们的内容。你可以找出满足你需要的那个。如果你找出了特定字段的工作方式的话,你可以将代码贴到这里来。

      相关链接:http://drupal.org/node/31646 , Think in Drupal

Drupal版本:

Organic Groups小组页面的drupal主题化

我看到很多人发帖询问如何为OG首页定制主题.我自己也想对drupal4.7版本的旧式OG首页进行升级,但是我还不能找到一种像样的方式。文档中(至少我看到的是)看起来仅仅告诉我们如何为实际的group(组)节点类型定制主题(例如node-og.tpl.php),或者在默认的og_ghp_ron主题加点过滤器。这些都不是本文要讨论的。(译者注,这里所讲的首页,是小组的首页,而不是站点的首页,一个站点可以有n多个小组,每个小组有一个自己的首页面)。

 

让我们假定你想为你的OG首页展示的所有帖子定制主题的话。你想让这些在OG展示的帖子与它们独立的节点页面以及teaser列表页面有所区别。而对于所有的小组首页采用相同的主题方式。这是我所要讲解的(如果你想让每个小组的首页都不同的话,你仍然可以使用这个代码,或者你还可以使用views)。我觉得应该有更好的方式,我也听到有人说,这很容易,但是没有看到过讲解如何去实现的帖子。所以我只能采用我的笨方法了。

 

在本教程中,我们将定你的og节点类型叫做'og'。如果你不知道你的叫做什么,可以访问admin/og/og,并点击"group home page"。这里所选的就是你的og节点类型。

 

还有,你需要先备份你的站点,这样当你觉得不对劲的时候,还可以恢复原貌。

 

我想使用一种通用的方式,因为我不想,当我添加一个新的小组时,需要更新我的节点文件。我也不想让小组的创建者为小组创建一个路径别名。(当然,如果只有一个人能够创建小组,而且小组的数量也不多的话,你也可以手工的在小组编辑表单页面设置小组的路径别名,而不用安装pathauto模块;这取决于你)。

 

我首先要做的是安装Pathauto模块。Pathauto允许你为你的任何内容创建用户友好的url路径。按照Pathauto模块的readme里面的说明,进行安装,完成以后,访问admin/settings/pathauto,点击"node path settings"。如果你仅仅想为你的小组添加别名的话,那么在节点部分的顶部,删除"Default path pattern (applies to all node types with blank patterns below)"(默认路径模式(适用于所有的节点类型,如果下面的模式为空的话))下面的东西。

如果你没有设置这一项的话,所有的内容都将采用默认路径模式来设置别名。Pathauto是一个非常方便的模块,如果你想采用默认的模式的话,我鼓励你好好的读一下配置页面的说明文字。对于本教程,就放心把它删除了吧。

 

现在,在同一部分里面,找到"Pattern for all og paths"(根据你的og节点类型名会有所不同)。在下面的输入框中,输入:groups/[title-raw]。

 

把页面往下拉,选中复选框"Bulk generate aliases for nodes that are not aliased"(为已有的没有别名的节点批量生成别名)。保存。现在你的所有小组首页面应该都有一个自动的用户友好的别名了。好极了。

 

现在,我们已经找到了一种方式,帮助节点识别我们是否处于小组首页面,现在就可以编辑我们的模板文件了。进入你的主题文件夹下面,编辑名为node.tpl.php的文件。

 

与普通的node.tpl.php文件唯一不同的是,我们需要检查pathauto别名,来看看我们是不是处在小组首页面上。然而,我们仅需要URL的第一个参数(也就是"groups"部分),所以我们还需要使用PHP字符串函数对别名进行截取。下面的是我写的代码片断,最后为完整的代码。下面是如何决定我们是否处于小组首页面:

相关联接:http://drupal.org/node/293906 , Think in Drupal

Drupal版本:

Organic Groups首页节点的drupal主题化(代码)

 

<?php
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    $url_alias = drupal_get_path_alias('node/'.arg(1));
  } elseif (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
    $url_alias = drupal_get_path_alias('taxonomy/term/'.arg(2));
  }

  // We need to only take the first argument of the aliased path, so define the separator
  $slash = '/';

  // find out if the separator exists in the returned alias
  $pos = strpos($url_alias, $slash);

  // if the separator is not present, then just look at the URL alias; if it is present, strip the first argument only
  if ($pos === false) {
  $string = $url_alias;
  } else {
  $string = substr($url_alias, 0, $pos);
  }
 
  // if the first argument of the aliased path == 'groups', then we know it's a group home page
  if ($string == 'groups'){ ?>

 

接下来,我们将格式化小组首页面的节点。在这里,我仅需要一个带有链接的标题,以及作者,发表日期,所以代码如下:

<?php if ($page == 0) { ?>
      <div class="content"><a href="<?php print $node_url; ?>"><?php print $title?></a><span class="submitted"><?php print " ".$user_name. " " . $date; ?></span></div>
    <?php }; ?>

 

 

接下来,如果别名不是'groups'的话,我将提供一个普通的teaser视图(view):

<?php
  // if the first argument of the aliased path wasn't 'groups', then it's a normal teaser view
  }else{ ?>
    <div class="node<?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-unpublished"; } ?>">
    <?php if ($picture) { print $picture; }?>
    <?php if ($page == 0) { ?>
      <h2 class="title"><a href="<?php print $node_url; ?>"><?php print $title?></a></h2>
    <?php }; ?>
    <span class="submitted"><?php print $submitted?></span> <span class="taxonomy"><?php print $terms?></span>
    <div class="content"><?php print $content?></div>
    <div class="clr">
    <?php if ($links): ?>
      <div class="links"><?php print $links; ?></div>
    <?php endif; ?>
    </div>
    </div>
  <?php } ?>

 

 

接着,让我们添加独立的节点视图(view),从而完成我们的node.tpl.php文件。

 

下面是完整的可用的代码

(你可以根据需要自己定制外观):

<?php if ($teaser): ?>

  <?php
  // we just get the drupal path args so that we can look up the path alias
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    $url_alias = drupal_get_path_alias('node/'.arg(1));
  } elseif (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
    $url_alias = drupal_get_path_alias('taxonomy/term/'.arg(2));
  }

  // We need to only take the first argument of the aliased path, so define the separator
  $slash = '/';

  // find out if the separator exists in the returned alias
  $pos = strpos($url_alias, $slash);

  // if the separator is not present, then just look at the URL alias; if it is present, strip the first argument only
  if ($pos === false) {
  $string = $url_alias;
  } else {
  $string = substr($url_alias, 0, $pos);
  }
 
  // if the first argument of the aliased path == 'groups', then we know it's a group home page
  if ($string == 'groups'){
  // below this is where you need to put your node formatting for the og home page ?>

    <?php if ($page == 0) { ?>
      <div class="content"><a href="<?php print $node_url; ?>"><?php print $title?></a><span class="submitted"><?php print " ".$user_name. " " . $date; ?></span></div>
    <?php }; ?>
 
  <?php
  // if the first argument of the aliased path wasn't 'groups', then it's a normal teaser view
  }else{
  // below this is where you need to put your normal node teaser formatting ?>
    <div class="node<?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-unpublished"; } ?>">
    <?php if ($picture) { print $picture; }?>
    <?php if ($page == 0) { ?>
      <h2 class="title"><a href="<?php print $node_url; ?>"><?php print $title?></a></h2>
    <?php }; ?>
    <span class="submitted"><?php print $submitted?></span> <span class="taxonomy"><?php print $terms?></span>
    <div class="content"><?php print $content?></div>
    <div class="clr">
    <?php if ($links): ?>
      <div class="links"><?php print $links; ?></div>
    <?php endif; ?>
    </div>
    </div>
  <?php } ?>

<?php else:
// here is where your full node formatting goes ?>

<div id="node-<?php print $node->nid; ?>" class="node<?php if ($sticky) { print ' sticky'; } ?><?php if (!$status) { print ' node-unpublished'; } ?> clear-block">

<?php print $picture ?>

<?php if ($page == 0): ?>
  <h2><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2>
<?php endif; ?>

  <div class="meta">
  <?php if ($submitted): ?>
    <span class="submitted"><?php print $submitted ?></span>
  <?php endif; ?>

  <?php if ($terms): ?>
    <span class="terms"><?php print $terms ?></span>
  <?php endif;?>
  </div>

  <div class="content">
    <?php print $content ?>
  </div>

<?php
  if ($links) {
    print $links;
  }
?>

</div>

<?php endif; ?>

Hopefully that will help save somebody time.

希望本文对读者能有所帮助。

 相关联接:http://drupal.org/node/293906Think in Drupal

 

Drupal版本:

节点摘要(teaser)的drupal主题化

你可以在drupal主题的node.tpl.php模板文件中使用下面的条件语句,来为摘要创建一个独特的外观:

<?php
if ($teaser) {
//if node is being displayed as a teaser
//Anything here will show up when the teaser of the post is viewed in your taxonomies or front page
} else {
//all other cases
//Anything here will show up when viewing your post at any other time, e.g. previews
?>

 

或者,你想在条件语句中使用HTML,例如使用模板创建两个完全不同的布局:

  <?php if ($teaser): ?>
    <!-- teaser template HTML here -->
  <?php else: ?>
    <!-- regular node view template HTML here --> 
  <?php endif; ?>

 

注意$page变量用来判断节点是不是单独处在一个页面中,这与是否是作为摘要(teaser)显示的是有区别的:在节点的编辑预览页面, $page都为true的.

 

 相关链接:http://drupal.org/node/53464 , Think in Drupal

drupal的Page.tpl.php

这个模板文件定义了页面的骨架.

 

可用变量(按字母顺序)

$base_path

返回Drupal安装的URL基路径.最初,这将默认为/。

$breadcrumb

在页面顶部用于展示面包屑的breadcrumb。

$closure

需要放在页面的底部,在页面展示出来后,用于动态javascript的调用。

$content

由Drupal生成的要展示的HTML内容。

$css

一个数组,包含了当前页面的所有CSS文件。

$directory

主题所在的目录,比如themes/garland or themes/garland/minelli.

$feed_icons

一个字符串,表示当前页面的所有种子的图标。

$footer_message

在管理设置页面(admin/settings/site-information)定义的页脚信息。

$head

由drupal_get_html_head()生成的HTML。

$head_title

在页面标题中要展示的文本。

$help

动态帮助文本,主要用于drupal的后台管理页面。

$is_front

如果当前页面为首页的话返回true。一般和mission(使命)结合使用。

$language

Drupal站点当前使用的语言。

$layout

这个设置允许你为不同的布局('none', 'left', 'right' 或者'both')使用不同的样式,这以来于你的布局结构。

$logo

Logo图片的路径,可在主题配置页面中定义。

$messages

HTML状态信息和错误信息,展示在页面的顶部。

$mission

Drupal站点的使命文本,当在主题设置中禁用了的话,那么为空。

$node

(drupal5.x及更高版本)如果你要在page.tpl.php中展示一个单独的完整的节点页面视图的话,那么就可以在你的模板中使用$node变量.

$onload_attribute

(drupal4.7及以前版本)在<head>标签中,添加onload标签,从而允许附带脚本的自动执行。

$primary_links (array)

一个包含了链接的数组,可以在phptemplate特定的配置区块中定义这些链接。

$scripts

(drupal5.x及更高版本)用来加载JavaScript文件,并使得JS设置可用的HTML。在以前,javascript文件是硬编码到page.tpl.php中去的。

$search_box

如果启用了搜索框的话,返回true。

$search_button_text

(drupal4.7及以前版本)搜索按钮上的翻译了的文本。

$search_description

(drupal4.7及以前版本)搜索按钮的翻译了的描述。

$search_url

(drupal4.7及以前版本)搜索表单要提交到的URL。

$secondary_links (array)

一个包含了链接的数组,可以在phptemplate特定的配置区块中定义这些链接。

$sidebar_left

用于左栏的HTML内容。

$sidebar_right

用于右栏的HTML内容。

$site_name

Drupal站点的名字,当在主题设置中禁用了该项的话,那么为空。

$site_slogan

Drupal站点的口号,当在主题设置中禁用了该项的话,那么为空。

$styles

用于样式表的切换。这将输出所需要的样式标签。

$tabs

在页面顶部展示的HTML标签(tab)

$title

标题,与head_title是不同的,这个在大多数时候指的是节点标题。

 

相关链接: http://drupal.org/node/11812 , Think in Drupal

Page.tpl.php(drupal默认模板)

默认模板

下面是Drupal 5的bluemarine主题的page.tpl.php模板,让你对页面模板文件有个实际的认识。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $language ?>" xml:lang="<?php print $language ?>">

<head>
  <title><?php print $head_title ?></title>
  <?php print $head ?>
  <?php print $styles ?>
  <?php print $scripts ?>
  <script type="text/javascript"><?php /* Needed to avoid Flash of Unstyle Content in IE */ ?> </script>
</head>

<body>

<table border="0" cellpadding="0" cellspacing="0" id="header">
  <tr>
    <td id="logo">
      <?php if ($logo) { ?><a href="<?php print $base_path ?>" title="<?php print t('Home') ?>"><img src="<?php print $logo ?>" alt="<?php print t('Home') ?>" /></a><?php } ?>
      <?php if ($site_name) { ?><h1 class='site-name'><a href="<?php print $base_path ?>" title="<?php print t('Home') ?>"><?php print $site_name ?></a></h1><?php } ?>
      <?php if ($site_slogan) { ?><div class='site-slogan'><?php print $site_slogan ?></div><?php } ?>
    </td>
    <td id="menu">
      <?php if (isset($secondary_links)) { ?><?php print theme('links', $secondary_links, array('class' =>'links', 'id' => 'subnavlist')) ?><?php } ?>
      <?php if (isset($primary_links)) { ?><?php print theme('links', $primary_links, array('class' =>'links', 'id' => 'navlist')) ?><?php } ?>
      <?php print $search_box ?>
    </td>
  </tr>
  <tr>
    <td colspan="2"><div><?php print $header ?></div></td>
  </tr>
</table>

<table border="0" cellpadding="0" cellspacing="0" id="content">
  <tr>
    <?php if ($sidebar_left) { ?><td id="sidebar-left">
      <?php print $sidebar_left ?>
    </td><?php } ?>
    <td valign="top">
      <?php if ($mission) { ?><div id="mission"><?php print $mission ?></div><?php } ?>
      <div id="main">
        <?php print $breadcrumb ?>
        <h1 class="title"><?php print $title ?></h1>
        <div class="tabs"><?php print $tabs ?></div>
        <?php print $help ?>
        <?php print $messages ?>
        <?php print $content; ?>
        <?php print $feed_icons; ?>
      </div>
    </td>
    <?php if ($sidebar_right) { ?><td id="sidebar-right">
      <?php print $sidebar_right ?>
    </td><?php } ?>
  </tr>
</table>

<div id="footer">
  <?php print $footer_message ?>
</div>
<?php print $closure ?>
</body>
</html>

$layout (drupal 5.x) 和 $body_classes (drupal 6.x)

PHPTemplate在page.tpl.php中提供了一个变量,如果你知道怎么使用的话,它将非常强大.

 

Drupal 5 ($layout)

$layout包含一个字符串,用来告诉你页面的布局:

如果用的是左栏的话,则为left

如果用的是右栏的话,则为right

如果左右栏都用的话,则为both

 

Drupal 6 ($body_classes)

      一个更强大的变量, $body_classes变量包含了一些由空格分隔的非常有用的信息,你可以在你的css类中使用它.

  • 是否处在首页? front / not_front
  • 已登陆或者退出了登录? logged-in / not-logged-in
  • 当前节点类型? node-type-??
  • 我们的边栏在做什么? two-sidebars / one-sidebar sidebar-left / one-sidebar sidebar-right / no-sidebars

一些Drupal 5主题已经实现了这些类,比如Zen

 

用它来增加你的优势

当你把这些变量放到类中的时候,这将使得你的主题更强大,扩展性也更强。这些变量的字符串,就是专门针对CSS类进行设计的。

 

 相关联接:http://drupal.org/node/171906 , Think in Drupal

Drupal版本:

drupal中如何调用额外的CSS文件

使用drupal_add_css()函数可以将其它的样式表添加到样式表数组中去:

<?php
// Repeat this line for every CSS file added.
drupal_add_css(path_to_theme() . '/example.css', 'theme', 'all', TRUE);
// Reassemble the $styles snippet to include the new files.
$styles = drupal_get_css();
?>

 

在这个例子中,我们是从主题文件夹下取得的example.css文件.当然你也可以把样式表放到files目录下,这样就不用使用path_to_theme()函数了,此时你就可以直接这样用'files/subdirectory/example.css'.

 

drupal_add_css()函数的参数分析:

  1. 1,样式表文件的路径(相对于base_path()的路径)
  2. 2,要添加样式表的类型(module 或者theme)

    •     样式表的调用时有顺序的,首先是系统的样式表,接着是模块的样式表,最后是主题的样式表.如果你想使用样式表覆写以前的CSS的话,你可以选择使用theme选项,这样它将处于数组的最后面,因此也将被最后调用。
  3. 3,样式表所应用的Media(媒体)(all, screen, print, handheld,等等)
  4. 4,最后是预处理选项(TRUE, FALSE),如果在管理界面的性能部分(admin/settings/performance)如果启用了这一特性的话,将会对样式表进行聚合和压缩。

 

 

对于Drupal 4.7.x

<?php
print $head;
print theme('stylesheet_import', base_path() . path_to_theme() . '/your_extra.css');
print $styles;
?>

因此,这就是样式表的最终顺序:

  1. 1,drupal.css
  2. 2,模块CSS(例如,event.module的event.css)
  3. 3,主题CSS(例如,your_extra.css)
  4. 4,样式CSS(来自任何主题的style.css文件)

样式表可以对前面的CSS规则进行覆写(例如,style.css可以覆写它前面的所有的CSS,除了用户CSS)。

相关链接: http://drupal.org/node/66122 , Think in Drupal

Drupal版本:

根据当前路径使用不同的drupal页面模板

在Drupal 5.0中, PHPTemplate支持在一个主题下,使用多个页面模板.根据当前的url路径(例如node/1, taxonomy/term/2, 或者user/1),PHPTemplate会按照顺序寻找相应的模板,如果找不到的话,将会采用默认的page.tpl.php模板文件。

 

例如,如果你访问http://www.example.com/node/1/edit,PHPtemplate将按照降序寻找下面的模板:

page-node-edit.tpl.php
page-node-1.tpl.php
page-node.tpl.php
page.tpl.php

 

如果你访问的是http://www.example.com/tracker,PHPTemplate将寻找下面的模板:

page-tracker.tpl.php
page.tpl.php

 

这一规则还适用于用户和分类的url。当访问http://www.example.com/user/1时 ,PHPtemplate将按照降序寻找下面的模板:

page-user-1.tpl.php
page-user.tpl.php
page.tpl.php

 

注意,首页是个特殊的情况(它的URL是http://example.com,后面没有相对路径了)。对于这种情况,你可以使用下面的模板:

page-front.tpl.php

 

记住,这些模板建议是基于drupal的内部路径的。如果你使用了path 或者pathauto模块的话,那么你看到的将是路径的别名。但是对于这些模板来说,他们仍然是基于drupal内部路径的。如果你想基于URL别名使用模板的话,可参看基于URL别名的不同页面模板一文。

如果你需要基于其它的一些规则来切换页面模板文件的话(例如,登录用户的角色),你可以在你主题的template.php文件中实现phptemplate_variables()函数。$vars['template_files']变量存储了一个可能的tpl.php文件数组,使用先进后出的规则。

Drupal版本:

为节点类型、术语、章节、路径、首页定制主题(Drupal4.x)

注意:对于Drupal 5,你可参看相应的文章http://drupal.org/node/104316

 

你可以为单篇文章、URL路径、分类术语、章节、和你的首页定制主题。

对于节点、页面和其它的主题定制的更全面的例子,可参看手册的PHP Template Snippets >> Customising full page layouts and sections

 

一种方式是使用sections module,来为你站点的不同部分使用不同的主题。然而,如果你的自定义主题或者模块拥有自己的主题模板文件的话,比如event(事件)模块,它需要许多重复的CSS和图片资源。

 

在一个Drupal站点上使用多个主题的关键是,由主题引擎决定当前你在站点中所处的位置。下面是我们可以从模板引擎中检查的一列条件。

 

$is_front phptemplate变量可用来检查当前是否处于首页。

<?php
if ($is_front) {
  include('front.tpl.php');
  return;
}
?>

 

Drupal的arg()函数用来得到路径中的参数。

arg(0)=="admin"// is /admin
arg(0) =="node"// is /node
arg(0)=="user" // is /user
arg(0)=="node"&&arg(1)=="add" // is /node/add
arg(0)=="node"&& arg(2)=="edit" // is /node/###/edit
arg(0)=="user"&&arg(1)=="add" // is /user/add
arg(0)=="admin"&&arg(1)="user"&&arg(2)=="create" // is /admin/user/create
arg(0)=="alias"&&arg(1)=="alias1" is /alias/alias1
arg(0)=="taxonomy"&&arg(1)=="term"&&arg(2)=="term#" // is /taxonomy/term/term#

//arg(1)=="comment"
//arg(2)=="reply"

 

推荐阅读根据节点类型定制你的节点模板

 

一旦你知道了front_page的值,或者路径,那么我们就可以使用不同的主题模板,也可使用CSS文件,或者修改xHTML标签的CSS类了。本节将分成3个子页面。

 

  1. 1,使用一个特定的模板,比如front.tpl.php, admin.tpl.php, term#.tpl.php。

<?php
if ($is_front) {
    include 'front.tpl.php';
    return;
}
elseif (arg(0)=="taxonomy"&&arg(1)=="term"&&arg(2)=="term#") { // add argument of choice
    include 'term#.tpl.php';// add template of choice
    return;
}

 

  1. 2,另一种选择是,为站点的不同部分使用不同的CSS。在下面的例子中,我们将基于路径来决定当前所在的位置,然后使用不同的CSS。在下面的例子中,我们决定要添加哪一个CSS。

<?php
if ($is_front) {
    include 'page_front.tpl.php';
    return;
}
if ($node->type == 'nodetype') { // all pages on my site are 'nodetype'
    $my_path = explode("/", drupal_get_path_alias('node/'.$node->nid)); // all pages have path like 'section/page'
    $my_path = $my_path[0];
} else {
    $my_path = arg(0);
}
switch ($my_path) {
    case 'using':
        $section = 1;
        break;
    case 'education':
        $section = 2;
        break;
    case 'company':
        $section = 3;
        break;
    case 'image':
        $section = 4;
        break;
    case 'forum':
        $section = 5;
        break;
    default:
        $section = 0;
}
$css_section = 'section'.$section;
?>

  1. 3,我们也可以为要被主题化的xHTML直接添加CSS类。

PHPTemplate 主题:

在page.tpl.php的body标签中(来自于bluemarine):
<body <?php print $onload_attributes ?> >

将变为:
<body class=" <?php print arg(0); ?> " <?php print $onload_attributes ?> >

接着你就可以为管理页面使用.admin作为css父选择器了。

 

对于Smarty

在page.tpl的body标签中(来自于bluemarine_smarty):
<body{$onload_attributes}>

将变为:
<body class="{php} echo arg(0); {/php}"{$onload_attributes}>

 

当查看根节点时,这可能产生一个空的class属性值---可以在class中包含一个固定的前缀,从而阻止这种情况的发生。

drupal节点匹配主菜单链接

下面的代码片断,用来检查当前节点是否匹配一个主菜单链接.这段代码假定主菜单链接的格式为'/somepage'.

 

<?php if (count($primary_links)) : ?>
    <ul class="primary">
        <?php foreach ($primary_links as $link): ?>
            <?php preg_match("/<a\s*.*?href\s*=\s*['\"]([^\"'>]*).*?>(.*?)<\/a>/i", $link, $matches); ?>
            <?php if (('/'.drupal_get_path_alias('node/'.$node->nid))==$matches[1]): /* if $node exists */ ?>
                <li class="selected"><?php print $link?></li>
            <?php elseif ('/'.arg(0)==$matches[1]): /* else try to use arg */ ?>
                <li class="selected"><?php print $link?></li>
            <?php elseif ((drupal_get_path_alias('node/'.$node->nid)=='node/') && (arg(0)=='node') && ($matches[1]=='/')): /* else if home */ ?>
                <li class="selected"><?php print $link?></li>
            <?php else: ?>
                <li><?php print $link?></li>
            <?php endif; ?>
        <?php endforeach; ?>
    </ul>
<?php endif; ?>

 

在这段代码中,我们只使用了arg(0)进行检查,对于那些由drupal模块创建的类节点来说,可能并不适用.

 相关链接: http://drupal.org/node/45954 , Think in Drupal

Drupal版本:

如何为每个drupal页面生成<body> class/id属性

这个代码将为你drupal站点上的每个页面的<body>标签生成一个类(class)和id。

在你主题的页面模板文件(page.tpl.php)中,将已存在的<body>标签替换为下面的代码:

<body<?php print phptemplate_body_attributes($is_front, $layout); ?>>

      

并在你主题的template.php文件中添加下面的代码:

 

/**

* Sets the body tag class and id attributes.

*

* From the Theme Developer's Guide, http://drupal.org/node/32077

*

* @param $is_front

*   boolean Whether or not the current page is the front page.

* @param $layout

*   string Which sidebars are being displayed.

* @return

*   string The rendered id and class attributes.

*/

function phptemplate_body_attributes($is_front = false, $layout = 'none') {

 

  if ($is_front) {

    $body_id = $body_class = 'homepage';

  }

  else {

    // Remove base path and any query string.

    global $base_path;

    list(,$path) = explode($base_path, $_SERVER['REQUEST_URI'], 2);

    list($path,) = explode('?', $path, 2);

    $path = rtrim($path, '/');

    // Construct the id name from the path, replacing slashes with dashes.

    $body_id = str_replace('/', '-', $path);

    // Construct the class name from the first part of the path only.

    list($body_class,) = explode('/', $path, 2);

  }

  $body_id = 'page-'. $body_id;

  $body_class = 'section-'. $body_class;

 

  // Use the same sidebar classes as Garland.

  $sidebar_class = ($layout == 'both') ? 'sidebars' : "sidebar-$layout";

 

  return " id=\"$body_id\" class=\"$body_class $sidebar_class\"";

}

 

注意:这里你需要启用简洁url,才能正常使用。

 

使用例子:

使用了这段代码后,当你访问news/archive/2007页面时,你将看到下面的<body>属性:

<body id="page-news-archive-2007" class="section-news sidebar-left">

现在你要做的就是为整个站点的新闻栏目创建一套新的CSS规则:

.content { background-image: url("background.png"); }

.section-news .content { background-image: url("news.png"); }

 

如果你启用了路径别名模块的话,并且花了功夫为你的页面创建了多层级的路径,这样你就很容易将站点分为做个栏目,然后为每个栏目使用一个完全不同的布局(背景图片,颜色,宽度等等)。

 相关联接: http://drupal.org/node/32077 ,  Think in Drupal

Drupal版本:

基于URL别名使用不同的drupal节点模板

Drupal 5包含了一个非常有用的机制,可以为不同的页面、区块、节点等提供不同的模板。例如,你可以为'blog'节点类型添加一个模板node-blog.tpl.php,从而取代默认的node.tpl.php模板。对于页面模板,就更加方便了,所以你可以为特定节点创建特定的模板,可参看基于当前路径适用不同的页面模板一文。

 

通过_phptemplate_variables()函数,还可以编辑可能的"template suggestions"(模板建议)列表。例如,下面的代码片断就基于URL别名创建了额外的“suggestions”(建议)。这比使用内部Drupal路径的方法更强大。

 

<?php
function _phptemplate_variables($hook, $vars = array()) {
  switch ($hook) {
    case 'page':
   
      // Add node template suggestions based on the aliased path.
      // For instance, if the current page has an alias of about/history/early,
      // we'll have templates of:
      // node_about_history_early.tpl.php
      // node_about_history.tpl.php
      // node_about.tpl.php
      // Whichever is found first is the one that will be used.
      if (module_exists('path')) {
        $alias = drupal_get_path_alias($_GET['q']);
        if ($alias != $_GET['q']) {
          $suggestions = array();
          $template_filename = 'node';
          foreach (explode('/', $alias) as $path_part) {
            $template_filename = $template_filename . '_' . $path_part;
            $suggestions[] = $template_filename;
          }
        }
        $vars['template_files'] = $suggestions;
      }
      break;
  }
 
  return $vars;
}
?>

相关链接: http://drupal.org/node/117491 , Think in Drupal

Drupal版本:

基于节点类型使用不同的drupal页面模板

可以在你的template.php文件中修改一个模板的“模板建议”("template suggestions")列表。下面的代码片断,将根据当前页面的节点类型来添加页面模板建议。这样,你就可以为节点类型为新闻(news)的页面定义一个模板page-nodetype-news.tpl.php。

 

<?php
// Add additional template suggestions
function _phptemplate_variables($hook, $vars) {
  switch ($hook) {
    case 'page':  
      // Add page template suggestions based on node type, if we aren't editing the node.
      if ($vars['node'] && arg(2) != 'edit') {
        $vars['template_files'][] = 'page-nodetype-'. $vars['node']->type;
      }
      break;
  }
  return $vars;
}
?>

 

如果你使用的drupal主题为Zen的话,打开你的子主题的template.php文件,将SUBTHEME_preprocess_page()函数的注释去掉,并向其中添加以下代码(没有<?php 和?>标签):

<?php
  // Add page template suggestions based on node type, if we aren't editing the node.
  if ($vars['node'] && arg(2) != 'edit') {
    $vars['template_files'][] = 'page-nodetype-'. $vars['node']->type;
  }
?>

 

 相关链接:http://drupal.org/node/249726 , Think in Drupal

Drupal版本:

基于URL别名使用不同的drupal页面模板

可以在你的template.php文件中修改一个模板的“模板建议”("template suggestions")列表。下面的代码片断,将根据当前页面的URL别名来添加页面模板建议。这样你就可以为'music'路径或者目录下面的页面定义一个page-music.tpl.php模板文件了。

Drupal 5版本:

<?php
function _phptemplate_variables($hook, $vars = array()) {
  switch ($hook) {
    case 'page':
   
      // Add page template suggestions based on the aliased path.
      // For instance, if the current page has an alias of about/history/early,
      // we'll have templates of:
      // page-about-history-early.tpl.php
      // page-about-history.tpl.php
      // page-about.tpl.php
      // Whichever is found first is the one that will be used.
      if (module_exists('path')) {
        $alias = drupal_get_path_alias(str_replace('/edit','',$_GET['q']));
        if ($alias != $_GET['q']) {
          $suggestions = array();
          $template_filename = 'page';
          foreach (explode('/', $alias) as $path_part) {
            $template_filename = $template_filename . '-' . $path_part;
            $suggestions[] = $template_filename;
          }
        }
        $vars['template_files'] = $suggestions;
      }
      break;
  }
 
  return $vars;
}
?>





Drupal 6版本:

<?php
function phptemplate_preprocess_page(&$vars) {
  if (module_exists('path')) {
    $alias = drupal_get_path_alias(str_replace('/edit','',$_GET['q']));
    if ($alias != $_GET['q']) {
      $suggestions = array();
      $template_filename = 'page';
      foreach (explode('/', $alias) as $path_part) {
        $template_filename = $template_filename . '-' . $path_part;
        $suggestions[] = $template_filename;
      }
    }
    $vars['template_files'] = $suggestions;
  }
}
?>

 

变通

下面的是这个方法的一些变通应用。

在一个页面模板中仅修改一个CSS类。适用于那些不需要创建一个新的模板,仅需要修改CSS的情况。

<?php
    if (module_exists('path')) {
        $alias = drupal_get_path_alias($_GET['q']);
        $class = explode('/', $alias);
        print '<div class="page page-'.$class[0].'">';
    }
?>

对特定节点类型的修改限制:

<?php
      // (...)
      if(arg(0)=='node') {
          $vars['template_files'] = 'page_' . $vars['node']->type;
     }
     // (...)
?>

 

 相关链接: http://drupal.org/node/139766 , Think in Drupal

Drupal版本:

向你的drupal模板中添加额外的变量

这里的例子来自于Drupal的论坛讨论. $hook指的是变量可用的区域(比如,对于comment.tpl.php,它就是"comment").

 

这个函数需要定义在一个template.php文件中,这个文件放在主题目录下面(例如: themes/box_cleanslate/template.php).

<?php
function  _phptemplate_variables($hook, $vars) {
   switch($hook) {
     case 'comment' :
        $vars['newvar'] = 'new variable';
        $vars['title'] = 'new title';
        break;
   }
   return $vars;
}
?>

这个函数对phptemplate_comment返回的变量进行了处理,你在这里可以很方便的按照需求对变量进行调整.

现在,在你的comment.tpl.php文件中,可以使用一个新的名为$newvar的变量了.类似的, $title变量覆写了phptemplate_comment中该变量的值.

一个漂亮的技巧是用来计算每个钩子的调用次数,这样你可以传递过来另一个额外的参数了.如下所示:

<?php
function _phptemplate_variables($hook, $vars) {
    static $count;
    $count = is_array($count) ? $count : array();
    $count[$hook] = is_int($count[$hook]) ? $count[$hook] : 1;
    $vars['zebra'] = ($count[$hook] % 2) ?'odd' : 'even';
    $vars['seqid'] = $count[$hook]++;
    return $vars;
  }
?>

如果为偶数的话,就是'even';奇数的话就是'odd'.这意味着你可以为每个节点/区块/评论/其它,实现一个斑马线样式(也就是:颜色间隔切换).

接着你就可以为class='$zebra'设置一些样式了,用来处理颜色的切换.

 

另一个例子就是,节点标记,用来判断我们查看的是不是节点.当有人查看一片文章时,使用这个变量就可以处理不同项目的显示了.

<?php
function _phptemplate_variables($hook, $vars) {
  switch ($hook) {
    case 'page':
      if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
        $vars['content_is_node'] = TRUE;
      }
    break;
  }
  return $vars;
}
?>

注意,这里的切换有点老套,但是我还是这样用了,因为将来你可能需要添加更多的变量.在这种情况下,你就需要它了.

args()用来检查你的url是/node/NID/形式的,而不是/node/NID/edit或者/node形式的.如果找到了符合条件的,我们将这个标记设为TRUE.

相关链接:http://drupal.org/node/16383 , Think in Drupal

Drupal版本:

drupal PHPTemplate中的区域

从Drupal 4.7开始,主题可以实现任意数量的区域,用于区块或者其它内容的显示。你可以到Drupal的区块管理页面(admin/build/block)看一下,你将看到,实际上区域本质上就是一个容器,你可以向里面添加区块。你也可以使用PHP向区域中添加非区块内容。什么是区域呢,一个比较好的例子就是边栏。

这些区域可以用于整个页面,或者其它的主题元素中,比如接电或者评论。 

PHPTemplate引擎定义了5个默认的区域:left(左栏), right(右栏), content(内容), header(页首), 和footer(页脚)。为了实现这些区域,在drupal主题中,只需要在page.tpl.php模板文件中包含进变量$sidebar_left, $sidebar_right, $content, $header, 和$footer_message就可以了,比如,<?php print $header; ?>。

 

如何实现自定义区域

对于一个主题,如果你不想使用默认的区域,想自己定义一套的话,你可以使用_regions()钩子函数。在这种情况下,你的自定义区域,将会覆写PHPTemplate的默认区域。

如果在主题目录中还没有template.php文件的话,那么创建一个;如果有的话,就使用现有的。然后,打开template.php文件,向里面添加一个mytheme_regions()函数,用来定义你的区域。每个区域都需要一个名字(没有空格的字符串)和一个描述(展示给用户的文本,比如在区块管理页面)。在下面的代码中,我们为"mytheme"主题重新定义了除左栏以外的PHPTemplate的默认区域,还为它添加了两个新的区域。

 

<?php
function mytheme_regions() {
  return array(
    'right' => t('right sidebar'),
    'content' => t('content'),
    'header' => t('header'),
    'footer' => t('footer'),
    'floater' => t('floater'),
    'inline1' => t('inline 1')
  );
}
?>

注意:对于函数名,你需要注意几点:

  • 使用你的主题名来代替mytheme_regions(),比如bluemarine_regions()
  • 不要在区域名中使用连字符;可以使用下划线。
  • 还有,你的主题名是你的基主题名(base theme name),而不是你的style.css文件所在的目录。例如,box_cleanslate覆写了box_grey主题的style.css文件;在这里,你的函数名应该为box_grey_regions。

 

如何向页面写入主题的区域变量。

如果你需要在page.tpl.php中使用你的区域的话,你不需要为你的区域去创建一个变量,然后再将内容指定给它;PHPTemplate已经自动帮你完成了。你所需要做的就是,通过编辑你主题的page.tpl.php文件,将变量写入到页面。对于你定义的每个新的区域,只需要在page.tpl.php中加一个print语句就可以了。对于前面定义的'floater'区域,可以这样调用:

<?php  print $floater;?>.

 

当然,你可以使用HTML,CSS,PHP(这个可能用到)来为你的区域定制一个好看的外观。

相关联接: http://drupal.org/node/29139 , Think in Drupal

Drupal版本:

如何将drupal区域指定到节点,评论中

默认情况下,所有定义的区域都传递给page.tpl.php。但是只需要额外的几步,你也可以将特定的区域应用到其它的模板文件中:node.tpl.php,comment.tpl.php等等。下面是如何实现的。

在你定义区域的template.php文件中,定义一个_phptemplate_variables()函数(如果已经存在的话,就使用已有的)。在这里,你要做的就是将区域内容指定到一个特定的主题调用中。当调用_phptemplate_variables()时,将会向$hook变量传递一个主题参数,比如'node'。所以,使用下面的代码,我们可以将区域指定到节点模板文件中:

<?php
function _phptemplate_variables($hook, $variables) {
  // Load the node region only if we're not in a teaser view.
  if ($hook == 'node' && !$vars['teaser']) {
    // Load region content assigned via blocks.
    foreach (array('inline1') as $region) {
      $variables[$region] = theme('blocks', $region);
    }
  }
  return $variables;
}
?>

注意,我们在这里做了检查,确保不是处于一个'teaser'视图中,这样只有当处于完整的节点视图中时,才加载内置区域。

现在,在你的节点模板中,你就可以把区域变量包含进来了。下面是标准的phptemplate node.tpl.php模板加进'inline1'区域后的样子:

  <div class="node<?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-unpublished"; } ?>">
    <?php if ($picture) {
      print $picture;
    }?>
    <?php if ($page == 0) { ?><h2 class="title"><a href="<?php print $node_url?>"><?php print $title?></a></h2><?php }; ?>
    <span class="submitted"><?php print $submitted?></span>
    <span class="taxonomy"><?php print $terms?></span>
    <div class="content"><div class="floatleft"><?php print $inline1?></div><?php print $content?></div>
    <?php if ($links) { ?><div class="links">&raquo; <?php print $links?></div><?php }; ?>
  </div>

 

大多数情况下,你都会为你的区域添加一些样式,你可以像往常一样,通过主题的style.css文件来完成。例如,在这里,我们将让内置区域向左浮动:

div.floatleft {
  float: left;
}

由于一个节点的变量传递给了其它的节点模板,所以你也可以在node-type模板中实现你的自定义外观。

这种方式还可以应用到其它的主题元素中。下面的例子将特定的区域指定到了节点和评论中:

<?php
function _phptemplate_variables($hook, $variables) {
  // Load region content assigned via blocks.
  // Load the node region only if we're not in a teaser view.
  if ($hook == 'node' && !$variables['teaser']) {
    foreach (array('node1', 'node2') as $region) {
      $variables[$region] = theme('blocks', $region);
    }
  }
  else if ($hook == 'commment') {
    foreach (array('comment1', 'comment2') as $region) {
      $variables[$region] = theme('blocks', $region);
    }
  }
  return $variables;
}
?>

相关联接: http://drupal.org/node/29139 , Think in Drupal

Drupal版本:

没有区块的drupal区域

如果你想将内容指定到区域中,而又不通过区块来实现的话,你可以使用drupal_set_content()函数。这允许你绕过通常的区块机制,你可以尝试以下几点:

 

将内容设置到区域中

在你的模块代码中,将内容设置给区域。在这里,你可以使用themename_regions()数组中不存在的区域名。这样,这些区域对于区块来说就不可用,因此里面也就不会放置区块内容了。假定你的区域叫做'region1' 和'region2'。在你的模块中,可以这样做:

<?php
$output = 'whatever';
drupal_set_content('region1', $output);
?>

 

在template.php文件中,设置一个变量,并将区域内容指定给这个变量。

<?php
function _phptemplate_variables($hook, $variables) {
  // Load region content assigned via drupal_set_content().
  if ($hook == 'page') {
    foreach (array('region1', 'region2') as $region) {
      $variables[$region] = drupal_get_content($region);
    }
  }
  return $variables;
}
?>

 

输出你的内容
在你的page.tpl.php文件中,在需要的地方输出区域:

<?php
print $region1;
?>

相关联接: http://drupal.org/node/29139 , Think in Drupal

Drupal版本:

template.php:覆写其它drupal主题函数

如果你要覆写的主题函数不包含在基本列表中(block, box, comment, node, page),你需要将它告诉给PHPTemplate.

 

为了实现这一点,你需要在你主题目录下,创建一个template.php文件.这个文件以PHP开始标签<?php,但是这里不需要结束标签,推荐你不要使用结束标签.还有,在文件中,还需要包含用于主题覆写的存根(stubs),这些存根告诉引擎使用哪个模板文件,以及向其中传递哪些参数.

 

首先,你需要知道你要覆写哪个主题函数.你可以在Drupal API文档中找出一列这样的函数.我们在这里以theme_item_list()为例.

 

theme_item_list()大概是这样定义的:
<?php function theme_item_list($items = array(), $title = NULL) {  ?>

 

现在,你需要在你主题的template.php文件中加一个存根,如下所示:

<?php
/**
* Catch the theme_item_list function, and redirect through the template api
*/
function phptemplate_item_list($items = array(), $title = NULL) {
  // Pass to phptemplate, including translating the parameters to an associative array.
  // The element names are the names that the variables
  // will be assigned within your template.
  return _phptemplate_callback('item_list', array('items' => $items, 'title' => $title));
}
?>

我们将函数名中的“theme”替换为了“phptemplate”,并调用函数_phptemplate_callback()以将参数($items和$title)传递给PHPTemplate。

 

现在,你可以在你主题目录下,创建一个item_list.tpl.php模板文件了,它将用来替代原有的theme_item_list()。这个函数,与原有的theme_item_list()相比,应该采用相同的逻辑。

 

注意,你需要访问[ Administer -> Site building -> Themes ],从而刷新PHPTemplate的缓存,以识别出新添加的文件。但是从drupal4.6开始,就不需要这一步了。

 

除了Drupal标准的主题函数以外(API中所包含的),你还可以使用主题函数来覆写Drupal表单的外观。例如,对于由表单构建器函数构建的一个核心表单,你可以使用form_id来对其进行覆写。详情可参看这个实例

为维护(drupal Site Offline)页面自定义主题

Drupal 6.x提供了一种内置的phptemplate方式,对站点离线后的维护页面进行主题化---参看http://drupal.org/node/195435.

在Drupal 5.x中,许多帖子建议通过修改内核为该页面定制主题,但是这种想法很臭,而且没有必要,当然最后的结果也不一定好.下面是由Nax(http://drupal.org/user/25511)提出的一些比较好的方式,每种方式都有自己的优点:

 

  • 为维护页面定义一个自定义主题模板文件: http://drupal.org/node/58562#comment-266358

    •       优点: 与主题相集成;在admin/settings/site-maintenance页面可以方便的配置“站点离线消息”,并可通过该管理界面修改这一消息。
  • 为维护页面定义一个静态的Html页面,通过向template.php插入下面的代码,将页面重定向到这个html页面:

function phptemplate_maintenance_page($content, $messages = TRUE, $partial = FALSE) {
  drupal_goto('path/to/your/site-offline.html');
}

参看http://drupal.org/node/58562#comment-281490

  •  

    •     优点:非常简单;不需要为维护页面自定义主题。
    •     不足:没有使用管理界面的“站点离线消息”,对于那些不了解情况的管理员,会让其感到很困惑。

这两种方法都能工作,所以你可以根据你的情况选择一个适合自己的。

 

当开发你自定义的维护页面时,你需要注意几点:

  •     记住,站点已经离线,现在你不能够再调用数据库了,包括直接的或者间接的,都不可以,所以在这一点上你需要小心。
  •     记住,你的.htaccess文件对用户可以访问的文件夹进行了限制,所以你需要将静态html页面放在一个用户可以访问的文件夹下(比如,根目录下面)

 

如果你有什么建议或者更好的方法的话,可以在下面跟贴。

相关链接: http://drupal.org/node/235463 , Think in Drupal

Drupal版本:

在你的drupal主题中对css进行聚合

Drupal内置的CSS聚合工作原理是,在"files/css"文件夹下,创建一个聚合文件,可以创建多个这样的聚合文件,比如当一个css文件在特定页面不需要时,而在另一个页面则用得到,这时就会新建一个聚合文件,通过$styles变量将其输出到page.tpl.php中。然而,这种方式对于部分人是行不通的,例如,将drupal运行在多台前台终端服务器上,但是却没有共享的"files"文件夹(它们可以与主服务器进行同步,而编辑则向主服务器添加内容),并且启用了缓存。在这种情况下,在部分前台终端服务器上css就显示不出来了,这是由于返回的是缓存页面,而没有检查css文件是否存在。

 

  • 用户访问服务器1,生成一个缓存页面和聚合了的css
  • 缓存页面提供给访问者,不过这次是从服务器2上提供的。
  • 而缓存页面引用的css文件在服务器2上并不存在。

 

这个问题的解决方案是,由template.php来负责css的聚合,并将css文件缓存在主题目录下(在服务器间同步时,通常将这个目录排除在外,即使你包含了这个目录,它仍然管用)。

每当用户访问一个前台终端服务器时,将会对文件名和最近修改时间应用md5函数从而创建一个字符串。如果存在了一个以该字符串为名的文件的话,将会使用这个文件,否则,将会创建一个这样的文件,并将其保存到'cache'目录下。

 

所以,首先在你的drupal主题下面创建一个名为'cache'的子目录,修改相应的权限,这样当代码执行时可以向该子目录写入文件。

 

如果你使用了Zen主题,那可可以向你子主题的template.php添加下面的代码(首先需要检查一下,这个函数是否已经存在,如果存在的话,你需要把函数声明去掉,将代码添加到函数的最底部),将STARTERKIT改为你主题的名字。

 

function STARTERKIT_preprocess_page(&$vars) {
$css = drupal_add_css();
$css_arr = array();
$modifiedDates = '';
$fileString = '';
foreach($css['all']['module'] as $css_module => $css_module_on) {
if(file_exists($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_module)) {
$modifiedDates .= filemtime($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_module);
$css_arr[] = $_SERVER['DOCUMENT_ROOT'] . base_path() . $css_module;
$fileString .= $css_module . ',';
}

}
foreach($css['all']['theme'] as $css_theme => $css_theme_on) {
if(file_exists($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_theme)) {
$modifiedDates .= filemtime($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_theme);
$css_arr[] = $_SERVER['DOCUMENT_ROOT'] . base_path() . $css_theme;
$fileString .= $css_theme . ',';
}
}
$combinedContent = '';
$fileName = base_path() . path_to_subtheme() . '/cache/' . md5($fileString . $modifiedDates) . '.css';
$file = $_SERVER['DOCUMENT_ROOT'] . $fileName;
if(!file_exists($file)) {
foreach($css_arr as $css_file) {
$combinedContent .= PHP_EOL.PHP_EOL.file_get_contents($css_file);
}
$fh = fopen($file, 'w');
fwrite($fh, $combinedContent);
fclose($fh);
}
$vars['styles_aggregated'] = '<style type="text/css" media="all">@import "' . $fileName . '";</style>';
}

 

如果你用的是一个普通的主题的话,你需要向你的template.php文件中添加以下代码(同样,存在函数已经存在的情况):

 

function  _phptemplate_variables($hook, $vars) {
   switch($hook) {
     case 'page' :
$css = drupal_add_css();
$css_arr = array();
$modifiedDates = '';
$fileString = '';
foreach($css['all']['module'] as $css_module => $css_module_on) {
if(file_exists($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_module)) {
$modifiedDates .= filemtime($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_module);
$css_arr[] = $_SERVER['DOCUMENT_ROOT'] . base_path() . $css_module;
$fileString .= $css_module . ',';
}
}
foreach($css['all']['theme'] as $css_theme => $css_theme_on) {
if(file_exists($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_theme)) {
$modifiedDates .= filemtime($_SERVER['DOCUMENT_ROOT'] . base_path() . $css_theme);
$css_arr[] = $_SERVER['DOCUMENT_ROOT'] . base_path() . $css_theme;
$fileString .= $css_theme . ',';
}
}
$combinedContent = '';
$fileName = base_path() . path_to_theme() . '/cache/' . md5($fileString . $modifiedDates) . '.css';
$file = $_SERVER['DOCUMENT_ROOT'] . $fileName;
if(!file_exists($file)) {
foreach($css_arr as $css_file) {
$combinedContent .= PHP_EOL.PHP_EOL.file_get_contents($css_file);
}
$fh = fopen($file, 'w');
fwrite($fh, $combinedContent);
fclose($fh);
}
$vars['styles_aggregated'] = '<style type="text/css" media="all">@import "' . $fileName . '";</style>';
        break;
   }
   return $vars;
}

 

最后,在你的page.tpl.php中,注意将$styles替换为$styles_aggregated

 相关链接: http://drupal.org/node/254780 , Think in Drupal

 

Drupal版本:

例子:隐藏drupal日志消息

下面这个例子,讲述了在drupal中,如何使用主题函数来隐藏元素.这个例子向你展示了如何隐藏节点创建页面生成的日志消息.它将永远的隐藏日志消息盒子(box),所以,如果你将来需要用到这个盒子的话,就不能使用这段代码了.

 

<?php
/**
* Override node form
*/
function phptemplate_node_form($form) {
  // Remove 'Log message' text area
  $form['log']['#access'] = FALSE;
  return drupal_render($form);
}
?>

 

相关链接:http://drupal.org/node/204515 , Think in Drupal

Drupal版本:

排除drupal.css文件

可以通过覆写theme_stylesheet_import()函数来忽略drupal.css文件.只需要向主题的template.php文件中添加以下代码:

<?php
/*
  Do not include drupal's default style sheet in this theme !
*/
function phptemplate_stylesheet_import($stylesheet, $media = 'all') {
  if (strpos($stylesheet, 'misc/drupal.css') == 0) {
    return theme_stylesheet_import($stylesheet, $media);
  }
}
?>

 

使用一个自定义.css文件来代替drupal.css:

 

<?php
function phptemplate_stylesheet_import($stylesheet, $media = 'all') {
  if (strpos($stylesheet, 'misc/drupal.css') != 0) {
    $stylesheet = str_replace('misc/drupal.css', 'misc/mysite.css', $stylesheet);
  }
  if (strpos($stylesheet, 'misc/drupal.css') == 0) {
    return theme_stylesheet_import($stylesheet, $media);
  }
}
?>

将这段代码放到主题的template.php文件中,这将drupal.css文件切换为一个自定义的.css文件。有些drupal站点,你想让它看不出来后台是用drupal做的话,你就需要替换这个drupal.css文件。在这个例子中,我们拷贝了原来的drupal.css文件,将其重命名为mysite.css,并将其保存到名为misc的目录下。

 

注意strpos的使用,来自于PHP.net:

警告—这个函数可能返回一个布尔值FALSE,但是也可能返回与FALSE等价的非布尔值,比如0或者""。更多信息可参看布尔值部分。在这个函数中使用===操作符来测试返回值。

 

相关链接: http://drupal.org/node/23215 , Think in Drupal

Drupal版本:

使用自定义图片替换drupal种子(RSS)图标

最简单的方式是使用一个自定义图片来直接替换/misc/feed.png文件.如果不能这样做的话,你可以使用PHP来覆写默认的XML图标.

对于一个兼容PHPTemplate的主题,使用下面的步骤,你就可以轻松的将Drupal's feed icon图标替换为你自己的(不仅仅是边栏区块中的,对于页面底部的也同样适用).本文基于如何覆写一个主题函数的步骤.

  1. 创建一个新的主题,或者修改已有的主题
  2. 在drupal主题目录下面,创建一个名为template.php的文件,如果已经存在了的话,编辑这个文件.
  3. 在<?php ?>标签之间插入一下代码(如果phptemplate_feed_icon()函数已经存在了,需要将其完全替换掉):

function phptemplate_feed_icon($url) {
  $icon_url = 'path/to/new/icon';
  if ($image = '<img src="'. $icon_url . '" alt="'. t('XML feed') .'" />') {
    return '<span class="xml-icon"><a href="'. check_url($url) .'">'. $image .'</a></span>';
  }
}

  1. 访问Administer » Site building » Themes来注册这个新图标函数.
  2. 如果需要的话,启用主题.

 相关链接: http://drupal.org/node/34384 , Think in Drupal

 

Drupal版本:

将XTemplate主题转化为drupal PHPTemplate主题

首先,将xtemplate.xtmpl改名为original.xtmpl,这样这个主题就不再是xtemplate主题了.

创建page.tpl.php

  1. 1,将original.xtmpl的内容拷贝到page.tpl.php中
  2. 2,删除节点,评论,盒子和区块部分.在这些部分所在的位置添加以下代码:
    <?php echo $content ?>
  3. 3,将所有的"{"字符替换为"<?php print $"
  4. 4,将所有的"}"字符替换为"; ?>"
  5. 5,将"$footer"改为"$closure"
  6. 6,将"$message"改为"$messages"
  7. 7,由于在phptemplate中一级和二级链接是数组,所以你需要将其从"echo $primary_links;"改为theme('links', $primary_links);".对于二级链接也是这么改.
  8. 8,在区块部分,根据内容所在的位置,我们需要将$block改为$sidebar_left或者$sidebar_right.

 

 

创建node.tpl.php

  1. 1,将original.xtmpl中的节点部分拷贝到新文件node.tpl.php中.
  2. 2,和前面一样,将所有的"{" 和"}"字符分别替换为"<?php print $" 和"; ?>".
  3. 3,将$link改为$node_url.
  4. 4,将"$taxonomy"改为"$terms".
  5. 5,将"print $sticky;"改为"if ($sticky) { print " sticky"; }".
  6. 6,将"print $picture;" 改为"if ($picture) { print $picture; }".
  7. 7,由于page.tpl.php 和node.tpl.php将标题展示了两次.为了统一起来,你需要在$main = 1时才展示标题.所以你需要在标题所在的代码行中,添加下面的代码"<?php if ($main) { ?>...<?php } ?>".

 

 

创建 comment.tpl.php

  1. 1,将original.xtmpl中的评论部分拷贝到新文件comment.tpl.php中.
  2. 2,和前面一样,将所有的"{" 和"}"字符分别替换为"<?php print $" 和"; ?>".
  3. 3,将 "print $picture;"改为"if ($picture) { print $picture; }"

为了简洁起见,你可能想修改“new”的展示,只有当$new != ''时,才对其进行展示。

 

创建block.tpl.php

  1. 1,将original.xtmpl中的区块部分拷贝到新文件block.tpl.php中
  2. 2,和前面一样,将所有的"{" 和"}"字符分别替换为"<?php print $" 和"; ?>".
  3. 3,接着将$block->title改为$block->subject。

 

创建box.tpl.php

  1. 1,将original.xtmpl中的box(盒子)部分拷贝到新文件box.tpl.php中
  2. 2,和前面一样,将所有的"{" 和"}"字符分别替换为"<?php print $" 和"; ?>".

 相关联接: http://drupal.org/node/22019 , Think in Drupal

Drupal版本: