Drupal手册

随着使用Drupal的不断深入, 越来越发现它的迷人之处, 当然这期间也走了很多很多的弯路, 但是依靠Drupal中文社区官方主站的帮助, 大部分问题得以解决

这里收集和整理了一些关于Drupal的使用技巧和经验,其中有翻译自Drupal Documentation,也有自己的瞎猫碰死耗子摸索出来的。当然所有这些都不可能做到通晓Drupal,更多的时候可能也仅仅起到了入门的作用,主要是为了记录和给一些懒人看的。由于6.x的发布以及5.x的普及,因此不再讨论4.x的内容.

同时, Drupal强大的模块是不能忽略的, 但是几乎所有的模块都是老外开放的, 使用说明和介绍也全是洋文, 为了方便查找和统计, 我把一些主流的模块中文介绍汉化文件统统放到了Drupal业余爱好者, 它可能并不是很全面, 但希望能帮助你, 或者你也可以加入进来.

不是一个程序员,使用Drupal纯属兴趣,如果你遇到了问题,我很乐意为你解答,但是记住,其实我和你的水平差不多,因此也不要奢望太多哈哈.

开始Drupal

Drupal的安装非常简单,运气好的话5分钟就足够了。这个板块只是从个人角度讲了一些在安装、配置和使用Drupal时的注意事项和小窍门。

安装drupal

开始写这个题目的时候就有点犯难,不知道该从什么地方下手,因为从Drupal5.x开始,安装变得异常的简单,几乎不用说明什么。而且这里已经基本写的很详细了,我就偷懒不再多说了,另外,关于Drupal的基础操作使用可以参考DrupalChina上的最终用户指南基本站点设置。同样的,你还可以在那里找到如何安装模块如何安装主题,但这篇文章比较老了,其中提到的theme engine在5.x以后就不再需要了。

再多说一句,安装第三方的模块或主题,最好分别上传到/site/all/modules和/site/all/themes,这样非常容易管理和备份,如果是多站点请参考多站点的配置

Drupal6.x与5.x的安装有一些小小的、微不足道的区别,但并没有什么特别需要注意的。

安装Drupal唯一需要注意的是一下几点:

最后,附件中提供一分官方详细的安装手册(英文PDF)。

系统环境需求

一般情况下,如果你使用的是主机商提供的服务/PHP技术人员/使用集成PHP环境软件的人,你并不需要详细的查看这篇文章。

Web服务器

推荐: Apache

  • Apache 1.3 或者 Apache 2.x
  • Unix/Linux 或者 Windows主机
  • 若要开启简洁链接(clean urls),必须开启Apache的 'mod_rewrite'

Microsoft IIS

  • IIS5 或者 IIS6
  • 若要开启简洁链接(clean urls),需要第三方的插件支持

PHP

推荐: PHP 5.2 及以上版本
必需: PHP 4.3.5 或以上

  • PHP 5.2 及更高版本仅支持Drupal 4.7.5(或以上)和Drupal 5.1(或以上)
  • PHP 5.2 及更高版本将是Drupal 7的必需要求
  • Drupal 6需要至少16M或以上的PHP memory limit (之前版本则需要至少8MB或以上). 根据你的网站实际使用的各类模块, PHP memory limit可能会超过16MB.
  • 需要安装并启动PHP链接到你的数据库. Drupal目前支持的数据库链接方式包括: mysql , mysqli and pgsql
  • PHP XML扩展 (应用与blogapi, drupal 以及 ping 模块). 这个扩展功能在PHP中是默认开启的.
  • PHP需要进行如下配置(仅当php.ini-dist / php.ini-recommended不是默认设置时):
  • 这些设置一般都包含在默认的 .htaccess文件中, 因此你不需要十分清除它们. 但是如果想让.htaccess中对PHP的配置生效,必需:
    • 使用Apache或兼容服务器
    • .htaccess文件是可读的
    • PHP运行于Apache模块方式
  • 阅读PHP手册了解更多关于PHP配置
  • 在一些虚拟主机中,有些设置是不能修改的,因此请资讯你的主机服务商(其实一般的国内外主机商提供的配置都可以满足Drupal的要求)

数据库

推荐: MySQL 4.1 或 MySQL 5.0

  • Drupal 6支持MySQL 4.1或更高版本
  • Drupal 5.x 及以前的版本支持 MySQL 3.23.17或更高版本。强烈推荐MySQL 4.1或更高版本
  • 注意: Drupal必须使用MySql中的一些功能,这在某些廉价主机商那里是禁用的,你必须确保你拥有以下权限:
    SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES
    注意: 如果你的系统或主机运行在MySQL 4.1或以前版本,你可能会收到一个错误报告: "Client does not support authentication protocol requested by server", 请参考这里

PostgreSQL 7.4 或更高版本

  • 注意:一些第三方模块并不是使用严格的MySql代码,如果你熟悉PostgreSQL,请找到他们的错误并报告。(换句话说,还是别用PostgreSQL了)

目前Drupal暂不支持MS SQL和Oracle。

配置多站点(Multisite)

多站点安装是Druapl的一大特色,一套程序,做出多个不同的站点,统一维护统一升级,非常方便。如何安装多站点,其实在Drupal安装文件的INSTALL.txt里说的很清楚了。 未完待续。。。

Cron

Cron是个很神奇的东西, 具体是干嘛的我不是十分清楚, 我理解就是定时执行一个动作的功能, 类似于Windows中的计划任务.

Cron在drupal中应用的很重要, 搜索的索引就需要执行Cron, 运行一次, 搜索模块就会收集一下索引. 另外XML Sitemap也可能需要Cron.

下边就说两个Cron的应用实例.

在IXWebHosting中配置Cron

我用的主机就是IXWebHosting, 所以我简单研究了一下在这上边是如何配置Cron的.

首先进入IXWebHosting控制面板, 选择FTP Manager, 把Crontab打开

点击Edit可以看到下边的样子

前边的几个什么minutes,hours什么的就是定义什么时间执行, 有很多的高级用法, 比如在上半年的每个奇数月份的第二个星期的偶数天的每小时的10/30/45分钟各执行一次...当然了, 这么复杂的我也不会写@%$#^...

我们就先来个简单的, 一般流量不是很大的Druapl站点, 每个小时甚至每两个小时执行一次Cron就可以了. 因此我们在minutes中填上0, 也就是一个小时中的第0分钟开始, 后边的所有都填上*号, 代表每个的意思, 这就是会在每天每个小时的开始执行一次Cron.

最后Command, 也就是命令, 你得告诉Cron去哪执行. 我抄了一段在Dreamhost上可以用的命令:

curl --silent --compressed http://example.com/cron.php

然后保存即可.

在Windows下使用Cron

在Windows下使用Cron也很简单, 只需要很简单的配置一下就可以了.

  1. 打开"任务计划", 双击"添加任务计划", 开始任务计划向导
  2. 选择程序, 比如IE或者Firefire都可以(我推荐使用wget, 启动更快, 占用资源更少). 点击下一步.
  3. 给这个任务起个名字, 比如: My Cron Job. 接下来选择周期, 比如"每天". 下一步.
  4. 选择开始的时间, 下一步.
  5. 输入本机的用户名和密码, 下一步
  6. 勾选"在点击完成时....", 点完成.
  7. 在"任务"标签下, "运行"那里, 应该显示的是(比如IE):C:\Program Files\Internet Explorer\iexplorer.exe, 在这之后输入空格+运行Cron的网址, 全写下来应该是这个样子的:
    C:\Program Files\Internet Explorer\iexplorer.exe http://mysite.com/cron.php
  8. 然后在"计划"标签中设置更精确的时间, 打开高级按钮, 勾选上"重复任务", 比如"每一个小时", 因为之前我们在第三步选择的是每天, 那么这里的持续时间就是24小时.
  9. 最后点击确定就ok了. 有可能还需要再输入一遍密码.

如果任务到时间了没有启动, 那么在第七步中将C:\Program Files\Internet Explorer\iexplorer.exe前后加上引号, 即:

"C:\Program Files\Internet Explorer\iexplorer.exe" http://mysite.com/cron.php

最开始我提到过wget, 如果用这个的话, 第七步应该写成:

X:\somepath\wget.exe -q -O nul http://mysite/cron.php

其中, X是你的盘符,somepath是wget.exe的存放路径.

核心模块的使用

6.x的核心模块包括:

不同文章作者的评论样式

commnet模块可以定义当前文章作者发表的评论采用不同的样式, 或者指定其中的几个用户采用不同的样式.

方法如下:

打开site/all/themes/yourthemes/comment.tpl.php, 找到:
<div class="comment<?php print ($comment->new) ? ' comment-new' : ''; print ' '. $status ?> clear-block">

在其中加上一句:
print ($comment->uid == $node->uid) ? ' author-comment' : '';

最后的样子是:
<div class="comment<?php print ($comment->new) ? ' comment-new' : ''; print ($comment->uid == $node->uid) ? ' author-comment' : ''; print ' '. $status ?> clear-block">

实现的效果就是当前文章作者的评论采用.author-comment的样式

下一步就是定义author-comment样式了, 例如:
.comment .author-comment {background-color:#000;}

如果只指定某个用户的留言采用不同样式, 则应该加上这句:
print ($comment->uid == 1) ? ' author-comment' : '';

改变论坛显示的日期/时间

drupal论坛中的帖子日期/时间都是按照: "xxx时间以前" 来表示的
如果只想用年月日这样的方法表示, 也是可以的.
需要修改核心模块forum.modules

找到
$variables['time'] = isset($variables['topic']->timestamp) ? format_interval(time() - $variables['topic']->timestamp) : '';

替换为:
$variables['time'] = isset($variables['topic']->timestamp) ? format_date($variables['topic']->timestamp, 'medium') : '';

其中最后一个medium就是代表使用中等长度的时间格式, 也可以改成short或者long

需要提醒的是, 由于是修改核心模块, 下次升级的时候还需要这样改过来.

评论模块不显示"未验证"(not verified)

不显示"未验证"/"not verified"字样
如果你允许了匿名用户可以留言,那么当匿名用户留言后,在他的名字后边会显示"未验证"/"not verified"字样,目的是为了避免匿名用户使用已注册用户的名称进行伪造留言,但如果你不需要这么做(比如个人blog),那么可以在/includes/theme.inc文件中进行修改: 找到(一般在1073行)

$output .= ' ('. t('not verified') .')'; 

替换为
$output .= ''; 

第三方模块的使用

Drupal的默认安装之后,你可能觉得它什么都干不了,不过正因为如此,Drupal获得了史无前例的扩展性,丰富的模块让Drupal什么都是也什么都不是

那么,找了的需要的模块并安装就可以了吗?一般情况下,是这样的。但是如果你想要你的模块最大限度的发挥它的特性以及满足你最个性的需求,这时你还需要对模块至少进行简单的了解和改造,并且熟练掌握它的使用技巧。

这个篇章就主要收集和分享一些模块方面的技巧或教程,其中一半是亲身体验,另一半是翻译或转载。

Automatic Nodetitles 使用nid做标题

Automatic Nodetitles可以让你在没有输入标题的情况下自动添加一个标题, 但是由于其内在机制的原因, 当你设置使用nid为标题的时候, 无法创建, 因为Automatic Nodetitles是在文章创建之前就添加了这个标题, 而此时文章还未写入数据库, 也就不存在nid了. 不过有人给出了解决方法.

打开auto_nodetitle.module, 在74行添加如下代码:

/**
* Implementation of hook_nodeapi().
* Needed for newly saved nodes
*/
function auto_nodetitle_nodeapi(&$node, $op, $teaser, $page) {
// First check if this nodetype is auto_nodetitle enabled
$setting = auto_nodetitle_get_setting($node->type);
if ($setting == AUTO_NODETITLE_ENABLED || ($setting == AUTO_NODETITLE_OPTIONAL && empty($form_state['values']['title']))) {
switch ($op) {
// Now works for insert and update. Title is stored in database with db_query instead of node_save
case 'insert':
case 'update':
$types = node_get_types();
$pattern = variable_get('ant_pattern_'. $node->type, '');
if (trim($pattern)) {
$node->changed = time();
$node->title = _auto_nodetitle_patternprocessor($pattern, $node);
}
else if ($node->nid) {
$node->title = t('@type @node-id', array('@type' => $types[$node->type]->name, '@node-id' => $node->nid));
}
else {
$node->title = t('@type', array('@type' => $types[$node->type]->name));
}
drupal_set_message($node->title . t(' has been generated. Node id is ') . $node->nid);
db_query("UPDATE {node} SET title = '%s' WHERE nid = %d", $node->title, $node->nid);
db_query("UPDATE {node_revisions} SET title = '%s' WHERE nid = %d AND vid = %d", $node->title, $node->nid, $node->vid);
break;
      default:
        break;
    }
  }
}

这个方法我在auto_nodetitle 6.x-1.0版本测试通过, 据说也可用于5.x版本. 经过测试, 在5.x中, 这段代码也可以正常工作哦, 不过需要在大概47行, 替换掉

/**
 * Implementation of hook_nodeapi().
 */
function auto_nodetitle_nodeapi(&$node, $op, $form = NULL, $a4 = NULL) {
  if ($op == 'validate') {
    if ((auto_nodetitle_get_setting($node->type) == AUTO_NODETITLE_ENABLED) || ((auto_nodetitle_get_setting($node->type) == AUTO_NODETITLE_OPTIONAL) && empty($node->title))) {
      /*
       * Sets the node title.
       * We need to do this on validation because of two points: 
       *     It's early engouh to have node previews working and 
       *     it's late enough as CCK has already gone through the 'process form values' step 
       * 
       * As changes to $node are not persistent during validation, we use form_set_value()!
       */
      auto_nodetitle_set_title($node);
      form_set_value($form['title'], $node->title);
    }
  }
}

另外, 使用这个方法有一个缺点, 就是必须使用自动创建的标题而不能手动输入一个标题.

Tagadelic不显示more tags

在使用Tagadelic的时候,其自带的block会将对应的类别以标签云的形式显示出来,也可以自定义显示的数量,而在这个block的最后会出现一个more tags的连接至显示所有标签的页面,如果你不需要这个连接,可以这样做:

5.x版本的Tagadelic打开tagadelic.module,大概在307-314行,找到

/**
 * theme function to provide a more link
 * @param $vid - vocab id for which more link is wanted
 * @ingroup themable
 */
function theme_tagadelic_more($vid) {
  return "<div class='more-link'>" . l(t('more tags'), "tagadelic/chunk/$vid") . "</div>";
}

把这段代码删除就可以了。

在6.x版本中的Tagadelic,同样打开tagadelic.module,大概在331-338行之间,找到:

/**
 * theme function to provide a more link
 * @param $vid - vocab id for which more link is wanted
 * @ingroup themable
 */
function theme_tagadelic_more($vid) {
  return "<div class='more-link'>". l(t('more tags'), "tagadelic/chunk/$vid") ."</div>";
}

删除即可。

auto expire在正文中显示到期时间

auto expire是一个可以设置node有效期的模块, 但是它在正文中并不显示到期时间. 有高人给出了patch, 详见附件.

第一个附件是完整的auto expire模块包, 解压替换掉原来的即可. 而且提供了后台设置选项, 比较简单

第二个附件则只是一个patch, 将其覆盖原文件, 然后打开你sites/all/themes/yourtheme中的node.tpl.php中使用
 print $auto_expire['date'];
这个参数了

patch来自: http://drupal.org/node/510030

imagecache配合imagefield使用方法

imagecache的简单使用方法,我之前发表在DrupalChina,现在看来竟然都是一年以前的文章了,那时候刚刚接触drupal,呵呵。

需要的模块:
cck、imagefield和imagecache,版本4.7以上的应该都没问题,imagefield说是需要apache服务器,iis我没有,我本人的机器是winxp+apache2+php5+mysql5+drupal5.1,测试成功。

安装激活这些模块就不废话了,地球人都知道。

第一步
在imagecache设置中,新建两个presets
第一个(正文中的图)
namespace: yourcontentnode_mainimage(文件名,随便选,最后图片会在这个目录下生成)
action: scale
width: 400(根据你的喜好)
height: 400(根据你的喜好)
scale to fit: inside dimensions
weight: 1
第二个(摘要中的图)
namespace: yourcontentnode_thumbnail
action: scale
width: 100
height: 100
scale to fit: inside dimensions
weight: 0

第二步
在你的内容类别中,比如story中,或者新建一个也成,加入image字段。
其中有个Maximum resolution选项,不用添,作者的意思是如果不添这个尺寸,原图就不会被上传,省一些空间呵呵。其他的设置普通cck方法一样,自己随便设置吧。

第三步
在display选项中,teaser选择你刚才设置的那个缩略图目录yourcontentnode_thumbnail,full当然是正文图片的目录了yourcontentnode_mainimage。

第四步
ok了,你试试发一个story吧。不出意外,首页摘要中显示的就是缩略图,正文中是那个400*400的图片啦

第五步
可能你不满足仅仅是这样,我亲自实验了一下,通过views也可能在一个block或者page中显示这些图片,只是在Fields中add一个imagefield,在option中选择你想显示图片,缩略图或者正文中的400*400的图片,如果不选则显示原始图片。

总结:如此说来imagecache还是比较强悍的,同理能做出各种图片风格。
缺点:
1.生成的缩略图点击后直接打开了图片,但不能进到node中,不过这里有个解决方法 http://drupal.org/node/144139
2.现在我想的是,如何能让这些图片放到按照用户或者日期的文件夹下,要是都放在一个文件夹中,日后图片多了,程序或者管理员查找起来那是相当费劲。

node_images使用方法

这篇文章首发与以前老的blog中,后转发到DrupalChina,现在又转了回来。
关于图片模块,我的要求是能生成缩略图并被views提取,能按照用户id分别保存图片,上传的原图可以符合页面宽度,对上传数量、大小进行限制。
于是,image.module实在太庞大,每次上传一张图片等于发布一个node;imce不能自己生成缩略图而且还要加上[img]的过滤,之前的imagecache配合imagefield的方法不错,但是遗憾是又不能自己存入到用户id下的文件夹。找啊找,突然发现了一直仍在角落里的node_images!

1.首先到这个地址下载node_images http://drupal.org/project/node_images

2.打开node_images.module,找到

  $form['node_images_thumb_resolution'] = array(
    '#type' => 'textfield',
    '#title' => t('Resolution for thumbnails'),
    '#default_value' => variable_get('node_images_thumb_resolution', '100x100'),
    '#size' => 15,
    '#maxlength' => 7,
    '#description' => t('The thumbnail size expressed as WIDTHxHEIGHT (e.g. 100x75).'),
  );

在这段的后边添加下边的代码

$form['node_images_thumb_sizemethod'] = array(
    '#type' => 'select',
    '#title' => t('Thumbnail Generation Method'),
    '#default_value' => variable_get('node_images_thumb_sizemethod', 'fitLongestSide'),
    '#description' => t('This determines the way node_images calculates the size and aspect ratio of thumbnails. <strong>Fit to width</strong> or <strong>Fit to height</strong> scale the thumbnail proportionally until it is the width or height specified above, maintaining the aspect ratio of the original and disregarding the other thumbnail dimension. Useful if all thumbnails must be a certain width but height can vary, or all must be a certain height but width can vary. <strong>Fit to longest side</strong> is the TYPICAL, DEFAULT BEHAVIOR -- it scales the whole thing down so that whichever side is longer fits into the thumbnail "box." Original aspect ratio is maintained. <strong>Fit to shortest side</strong> is similar but matches whichever side is SHORTER to its corresponding thumbnail dimension. With this, there can be some spillover so the whole thing might not fit in the thumbnail "box" dimensions. Aspect ratio maintained. <strong>Crop and fit exactly</strong> is the gem; it fits the thumbnail to be EXACTLY the size specified above, cropping the longer side (centering the image in the crop rectangle).'),
    '#options' => array(
      'fitToWidth' => t('Fit to width'),
      'fitToHeight' => t('Fit to height'),
      'fitLongestSide' => t('Fit to longest side'),
      'fitShortestSide' => t('Fit to shortest side'),
      'fitExactSize' => t('Crop and fit exactly')
    ),
  );

再找到
/**
* Create the thumbnail for the uploaded image.
*/
function _node_images_create_thumbnail($path, $suffix='_tn') {

把这个function全部替换成下边的代码
function universal_thumbnail_calculator( $originalWidth, $originalHeight, $suggestedWidth, $suggestedHeight, $resizeMethod = 'fitLongestSide' ) {
 
  $ratioX       = $suggestedWidth/$originalWidth;
  $ratioY       = $suggestedHeight/$originalHeight;
  $crop = FALSE;
 
  if ($resizeMethod == 'fitExactSize') {
    $resizeMethod = 'fitShortestSide';
    $crop = TRUE;
  }
  if ($resizeMethod == 'fitLongestSide') {
    $resizeMethod = ($originalWidth > $originalHeight) ? 'fitToWidth' : 'fitToHeight';
  }
  if ($resizeMethod == 'fitShortestSide') {
    $resizeMethod = ($originalWidth < $originalHeight) ? 'fitToWidth' : 'fitToHeight';
  }
 
  switch ($resizeMethod) {
    case 'fitToWidth':
      $thumbnailValues = array( 'scaledX' => $suggestedWidth, 'scaledY' => round($originalHeight*$ratioX) );
    break;
    case 'fitToHeight':
      $thumbnailValues = array( 'scaledX' => round($originalWidth*$ratioY), 'scaledY' => $suggestedHeight );
    break;
  }
 
  if ($crop) {
        // Calculate the offset (where to begin 'drawing' the crop rectangle) as half the pixel overflow:
        $thumbnailValues['offsetX'] = round($thumbnailValues['scaledX'] - $suggestedWidth)/2;
        $thumbnailValues['offsetY'] = round($thumbnailValues['scaledY'] - $suggestedHeight)/2;
        // Pass along the "newly cropped" dimensions to be used by later code:
        $thumbnailValues['croppedX'] = $suggestedWidth;
        $thumbnailValues['croppedY'] = $suggestedHeight;
  }
 
  return $thumbnailValues;
}
 
/**
* Create the thumbnail for the uploaded image.
*/
 
function _node_images_create_thumbnail($path, $suffix='_tn') {
  $size = variable_get('node_images_thumb_resolution', '100x100');
  list($width, $height) = explode('x', $size);
  $dest_path = preg_replace('!(\.[^/.]+?)?$!', "$suffix\\1", $path, 1);
  $resizeThumbMethod = variable_get('node_images_thumb_sizemethod', 'fitLongestSide');
 
  if ($size = getimagesize($path)) {
        $currentWidth = $size[0];
        $currentHeight = $size[1];     
        $thumbnailDimensions = universal_thumbnail_calculator( $currentWidth, $currentHeight, $width, $height, $resizeThumbMethod);
 
        image_resize($path, $dest_path, $thumbnailDimensions['scaledX'], $thumbnailDimensions['scaledY']);
        if ((isset($thumbnailDimensions['offsetX']) && ($thumbnailDimensions['offsetX']>0)) || (isset($thumbnailDimensions['offsetY']) && ($thumbnailDimensions['offsetY']>0))) {
            image_crop($dest_path, $dest_path, $thumbnailDimensions['offsetX'], $thumbnailDimensions['offsetY'], $thumbnailDimensions['croppedX'], $thumbnailDimensions['croppedY']);
        }
 
        $info = image_get_info($dest_path);
        $thumb = new stdClass();
        $thumb->filename = basename($dest_path);
        $thumb->filepath = $dest_path;
        $thumb->filesize = $info['file_size'];
        $thumb->filemime = $info['mime_type'];
        return $thumb;
  }
  return NULL;
}
?>

这样做的目的稍后再讲,这个patch的原文 http://drupal.org/node/147538

3.上传激活这模块(同时还需要开启upload模块)

4.在站点配置里打开nodeimage,第一项就是可以选择存储目录uid或者username;第二项是生成缩略图的大小,比如80*80(在第二步中更改的那些代码就是为了修补这个小bug,node_images在上传一个比你设定的缩略图尺寸还小的图片时,无法生成缩略图);第三项可以选择图片上传是按照什么方式放大缩小,如适合宽度,适合高度等等(这也是第二步那个patch增加的一个功能);第四项就是图片格式;第五项是规定一个node中最多可以上传多少张图片;最后一个是md5格式的文件名。

5.还是站点配置,在文件上传中,第一个,上传图像的最大分辨率,这个数值就是node-images上传图片显示的大小。例如你再次设置500*500,即时你上传一张1280*800的图片,也会被压缩成500*500的规格,好处是避免了图片撑破页面,缺点是不适合清晰大图。

6.进入内容管理-内容类型,随便挑一个类型,比如story,打开编辑,在最下边,先看到有个Position,选择一下图片发表的位置;Link to image gallery这个可有可无,无非是点图片的时候打开一个简陋的小相册;其他都按个人喜好设置吧。

7.那么怎么发表图片呢?这个有点不方便,就是说你要在发表完一个node之后才出现一个image标签让你上传。

8.创建一个views block。在field中加上Node Images: Display node images和Node: Title(nodeimage点击缩略图不是进入node而是打开原图片。)过滤器中加上Node images: Has node images。其他看个人喜好了。

好了,大概就这些了。都是一些最基本的使用方法,还有一些可以增强node_images的功能,例如:
http://drupal.org/node/150904 支持Lightbox, Thickbox
个人认为,node_images应该是非图片站点的最佳图片解决方法,缩略图、自动压缩原图、views、按uid目录存储图片……多诱人,哈哈。

在Drupal中使用Google Custom Search

如果你觉得Drupal 搜索模块太庞大, 或者觉得它占资源, 再或者你的服务器不支持cron, 那么显然你需要另一个搜索引擎来帮助你. 又显然, 总所周知的Google Custom Search是个不错的选择.

首先, 你要先申请并配置一个GSE, 然后就是在drupal创建搜索框和搜索结果页了:
1.新建任意类型的一个内容, 比如page; 名字随便, 然后在正文中将GSE中的搜索结果代码复制进去, 输入法则选择full HTML, URL路径则设置为GCS中配置的路径, 比如/googlesearch, 最后提交即可, 搜索结果页就创建好了.
其中

var googleSearchFrameWidth = 520;
代表了搜索结果的页面宽度, 520就是520px, 其他参数稍微有点html基础的人都明白就不多说了.

2.新建一个block, 把搜索框代码复制进去, 同样记得输入法选择full HTML, 保存即可, 然后把这个block放到你喜欢的地方就成了.
这一步, 有个重点中的重点, 也是本文中最重要的部分, 搜索框代码需要进行一点点小小的修改才能正常的在drupal中工作.
找到

<input type="text" name="q" size="31" />
, 把name="q"修改为
name="query"
. 这是因为drupal的路径中也包括了"?q=", 如果不加修改, drupal就会傻乎乎的找不到页面了.
这一点我也是琢磨了好久才领悟出来的,哈哈.

3.好了, 大功告成, 现在你就可以用GSE完全替代drupal庞大复杂的search module了.

解决uploadpath使用日期无法创建目录的问题

当你将uploadpath的路径设置为日期形式时, 例如类似[yy][mm]/[dd], 在撰写一篇新的node中上传文件, 该文件的路径不能被正确创建, 这是因为node是新创建的, 而此时token还没有得到关于这个node的创建日期, 所以无法生成日期目录. 但是token的作者并不认为这是token的问题, 而uploadpath也没有给出解决方法, 但问题还是要有人解决, 比如yan就给出了解决方法:

打开/token/token_node.inc, 在第21行的前边, 也就是"if (isset($node->created)) {") 这句话之前添加一下代码:

if (empty($node->created)) {
  $node->created = time();
}

08年11月23日更新:
uploadpath 6.x-1.0版本的不再需要进行任何修改即可. 5.x的未测试.

08年12月12日更新:
uploadpath 5.x-1.1版本也不需要任何修改既能正常使用了!

PHP代码

Drupal的模块(modules)非常丰富和强大,但是一些简单的功能则可以依靠几个PHP代码来代替模块去实现,而另外一些地方可能和你想要的略有差异, 我们需要把它打造成我们需要的玩意儿.

不懂PHP?没关系,这里提供了很多PHP代码, 你可以方便的直接复制粘贴使用.

注意:

  1. 不同版本, 比如5.x与6.x的代码有可能不尽相同, 请注意区分. 另外, 在新增或修改任何PHP代码之前, 如果不能确定, 建议先备份一下数据库
  2. 所有的代码都是第三方提供的, 虽然都是经过千锤百炼过的, 但毕竟每个人的drupal站点都略有不同, 因此风险自负.

区块页面可见性PHP代码

在区块中,我们可以根据不同的url来规定一些区块是否显示,但是当url较多,或者有类似的url的时候,就不太好控制。下边的一些php代码可以更有针对性的来控制你的区块如何显示。仅适用于5.x!!!

只对特定角色的用户显示:

global $user;
$allowed = array('moderator','administrator');
$valid=FALSE;
foreach($user->roles as $role){
  if(in_array($role, $allowed)) {
    $valid=TRUE;
  }
}
return $valid;

不对特定角色的用户显示

global $user;
// These are the roles who should not see this block
$notallowed = array('anonymous user','artist','GoZabo Administrator', 'SuperAdmin');
 
// Assume they can see it to start
$valid=TRUE;
 
// Go through each role the user is in and, if we hit a role that is not allowed to see it, set valid to false
foreach($user->roles as $role){
  if(in_array($role, $notallowed)) {
    $valid=FALSE;
  }
}
 
// If no roles were hit that aren't allowed, this will still be true. Otherwise it will be false.
return $valid;

在指定的内容类型中显示区块

$match = FALSE;
$types = array('story' => 1, 'page' => 1);
if (arg(0) == 'node' && is_numeric(arg(1))) {
  $nid = arg(1);
  $node = node_load(array('nid' => $nid));
  $type = $node->type;
  if (isset($types[$type])) {
    $match = TRUE;
  }
}
return $match;

这个例子是说在story和page两个内容类型的页面上显示区块,你只要更改第二行'story' 和'page'为你需要的类型就可以了,比如book。

主题(theme)代码

主题, 就是脸, 内涵再丰富, 家底再丰厚, 没脸也是不行的...

所以这里我就尽量介绍一些关于主题方便的东西.

但是不得不承认, drupal的脸比WordPress少了许多也难看了许多, 然而DIY的空间却大了很多.

去掉/隐藏"格式化选项信息"

在发表node和评论时,正文文本框下方会显示格式化信息的提醒,例如:

* 网页地址和电子邮件地址将会被自动转换为链接。
* Allowed HTML tags:<ul> <ol> <li> <dl> <dt> <dd>
* 行和段被自动切分

如果你不希望显示这些信息, 在5.x版本下, 可以在你的主题template.php文件中添加如下代码:

/*
* Override filter.module's theme_filter_tips() function to disable tips display.
*/
function phptemplate_filter_tips($tips, $long = FALSE, $extra = '') {
  return '';
}
function phptemplate_filter_tips_more_info () {
  return '';
}

如果还希望保留更多格式化选项信息 链接, 那么(1)你可以在主题的css中添加这段样式:

ul.tips {display: none}

或者(2)是注销掉filter模块中filter.module的这段代码:

function theme_filter_tips($tips, $long = FALSE, $extra = '') {

不过方法一的缺点是那段提示并没有取消,而是隐藏了起来, 有可能对于SEO来说不是好事, 但问题不大; 方法二由于是修改了核心代码, 以后升级的时候一定记得别忘了还要继续修改.

这个方法并不适用于6.x, 如果是6.x, 你需要同时修改filter.module和template.php, 这是我我目前找到唯一方法.
打开template.php, 添加如下代码

function phptemplate_filter_tips($format, $long = FALSE) {
  return '';
}

打开filter.module, 大概在586行, 找到

function theme_filter_tips_more_info()

把下边的
return '<p>'. l(t('More information about formatting options'), 'filter/tips') .'</p>';
修改为
return '';

取消6.x截取摘要的按钮

6.x在发布node时, 在正文上方有一个在光标处截取摘要的按钮,

点一下就可以把光标以前的内容生成摘要, 也就是teaser, 无非就是自动增加了一个[!--break--]标签, 如果是自用, 用处和意义都不是很大, 而且影响美观, 那么我们就把这个功能去掉吧.

以下操作需要对核心文件进行修改, 目前来看不会产生什么副作用, 但也不能完全保证

第一步, 打开/misc/teaser.js, 从上到下注销所有内容
第二步, 打开/modules/node/node.pages.inc, 在大概280行, 删除或注销掉下列代码:

  $form['teaser_include'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show summary in full view'),
    '#default_value' => $include,
    '#prefix' => '<div class="teaser-checkbox">',
    '#suffix' => '</div>',
  );

增加评论标题(subject)的截取长度

Drupal的评论是需要填写一个标题的,如果不填写则会提取评论内容开头的几个字作为标题,可能你会觉得Drupal提取中文的长度不够多(默认7个汉字),那么你可以这样做: 打开/modules/comment/comment.module 修改下列代码中的29为一个更大的数字,建议40-50

$form_values['subject'] = trim(truncate_utf8(decode_entities(strip_tags(check_markup($form_values['comment'], $form_values['format']))), 29, TRUE));

其他/新闻/趣事

如题所示, 关于Drupal其他的一些事情.

另外官方网站也提供了足够多的Drupal动态和支持, 比如Drupal安全中心 , 新闻中心 , 这些内容都可以通过RSS来订阅.

Drupal怎么读?

首先,drupal据说是荷兰语水滴的意思,也就是英语中的drop。d-r-u-p-a-l,这六个小小的字母,单独一个都会读,放在一起还真不好下嘴。其实在Drupal中文社区讨论过Drupal的中文译名,甚至台湾Drupal还给出了一个swf读音

听了这么多版本,反正drupal的发音不好听,总的来说,写成中文就是:猪跑。

当然,如果按照贝宝(PayPal)的翻译方法,最后的pal可以音译为“宝”字,也就是“猪宝”,但猪宝毕竟不是猪宝宝,读起来还是很别扭。或者也可以读成“波”,这样可能会好一点。然而关键还是要看第一个音节dru。下边是我的几个设想:

  • 逐波——与joomla逐浪类似了
  • 竹波——很田园
  • 珠宝——很昂贵
  • 珠波——像个人名

都不怎么样,如果你也不确定的话,可以听听附件中那个洋妞的读法,截取自安装Drupal6的视频

Drupal的PR=9!

今天在Drupal上找资料的时候,好奇心驱使我去看看它的PR值,因为记得几个月前好像是7。这一看不要紧,好家伙,现在的PR竟然到了9!要知道myspaceyoutube这样的网站PR不过8而已,Drupal一个alexa排名好几千的开源程序官方网站能做到9只能说明2个问题:1个是程序本身实在太优秀;2是世界上大部分牛逼的网站和目录都链接到了Drupal

同时,Drupal中文社区,大概在上个月PR值也达到了7。这又是什么概念?sina不过也是7而已。所以,或许Drupal程序本身的确是十分强悍。当然了,PR的高低和程序之间是否有关系和什么关系我是一点都不得而知。我只知道,选择了Drupal,没错!嘿嘿。   

白宫奥巴马政府网站采用Drupal !

原文转自 http://www.cnbeta.com/articles/77543.htm <为何白宫会采用Drupal管理平台?>

当得知白宫的新网站Recovery.gov采用免费的,开源内容管理系统平台Drupal时,众多Drupal开发者都为此欢呼雀跃。在Recovery.gov之前,高调采用Drupal平台的网站可能就是Onion网站。但这不是让Drupal爱好者感到兴奋的唯一原因,笔者曾经向两位CMS(内容管理系统)专家朋友询问其中的状况,以下的原因能够解释为何Recovery.gov会大量采用Drupal平台:

首先,最现实的问题是,Drupal是免费的,按照目前的经济状况,转向开源可以节省纳税人的钱。

第二,这说明了白宫并没有就“社区合作开发的软件对于政府部门来说不够稳定和安全”的问题作过多的争辩。

第三,按理说,Drupal正在不断进步,它在民主政治方面有很深的根基,第一次引起政界注意的是Dean Space下的基金会出现,无论在哪个州,Drupal都拥有足够多的开发者社区进行开发。(还有David Cohn所写的Drupal政治历史

最后,Recovery.gov采用Drupal标志着白宫正和Blue State Digital一起从事开源工作,该公司是奥巴马竞选时的Internet大本营。BSD采用自己私有的CMS。

作为社区共建的系统,Drupal依赖于开发者对代码进行改进,虽然白宫也可以开发出一些构建和节点,但终归还是的回到Drupal世界去。Drupal大会也将在3月4日到7日在华盛顿召开。

简单对比Drupal vs WordPress

使用Wordpress是一种简单轻松的享受过程,华丽的界面,方便的自定义,广泛的使用基础,而且入门很低;而使用Drupal则是一种不断发现惊喜的过程。

个人Blog,Wordpress无疑是首选之一,简单的入门,高效的发布,漂亮的界面,说到外观,个人blog除了内容以外,外观也是精华之一,有时候甚至比内容还重要,毕竟它是展现blogger最前沿的舞台。而且,即便是在制作一个自己个性化的界面时,也相当的容易,在这方面,drupal基本败的一塌糊涂。使用wordpress是一个平滑的曲线,起点很低,从头到尾,基本不需要你增加新的知识。在用户群方面,尤其是中文用户群相当的丰富,即便29个英文字母一个都不懂,wordpress的中文化也足够你瞧的了。

反观drupal,如果你不是一个特专业的PHP程序员出身,那么在你安装好drupal之后的一个小时内,你就会感慨:druapl连狗屎都不如。是啊,丑陋的界面,缓慢的速度,简单的功能,无从下手的配置,甚至连个所见即所得的编辑器都没有。那么这时候,你应该先去想想Drupal适合你吗?如果答案是肯定的,那么打起精神,再花费几个小时甚至几天的时间,最多一个礼拜,你就会发现,drupal其实什么都是,也什么也都不是。 Drupal实际上是一个彻头彻尾的毛坯房,甚至中间连隔断和墙壁都没有,那么说它一块空地更恰当. 未完待续……

我使用的Drupal模块

个人blog,不需要太多的功能,我的原则是,能省就省。如果需要一个功能,在安装这个功能的插件时,我就先会试着看看现有模块能不能实现类似的功能,如果可以,那坚决不会安装一个新插件的。毕竟Drupal貌似对硬件的要求比较高,越多的模块自然会拖累网站速度,速度都没了,内容再优秀、页面再炫丽,人家看不了也瞎掰。目前使用的模块如下:(不断更改中,有删除线的代表不再使用)

Core Modules

Book
Comment
Contact
Locale太占资源改成自己手工翻译了
Menu
Path
Taxonomy
Upload

Contributed Modules

Administration Menu
BUEditor 发现新版本的FCK Editor更好用 后来又发现用不上这么功能强大的wysiwyg
FCK Editor理由见上边
Gallery很好很强大, 但可惜我发现我的照片/图片少的可怜
IMCE
Pathauto 后来发现没什么值得auto的path,所以也就不用了
CCK
Code Filter
Meta tags
CAPTCHA
Suggested Terms
Tagadelic
Tagadelic Views 精简modules的时候给精简掉了
Related Links
Views
String Overrides
XML Sitemap

更多模块介绍可以参考这里