2010年12月15日星期三
2009年4月16日星期四
不使用Locale模块本地化Drupal
/**如果你只需要翻译Drupal网站中的少部分字符串,那么就不需要开启Locale模块,再导入翻译包那样费劲了。在settings.php中,可以添加一些翻译字符串,Drupal在显示字符串时,会首先用这里面的字符串去进行替换。这样会省去很大一部分的资源消耗。比如:
* String overrides:
*
* To override specific strings on your site with or without enabling locale
* module, add an entry to this list. This functionality allows you to change
* a small number of your site's default English language interface strings.
*
* Remove the leading hash signs to enable.
*/
# $conf['locale_custom_strings_en'] = array(
# 'forum' => 'Discussion board',
# '@count min' => '@count minutes',
# );
$conf['locale_custom_strings_zh-hans'] = array(有两点需要注意:
'forum' => '讨论组',
'@count min' => '@count 分钟',
);
- 要翻译中文,需要使用locale_custom_strings_zh-hans
- 要将settings.php存为utf-8格式
Drupal项目实战-公司订餐系统(四)
在上面的文章中,我们已经创建了一个Food节点类型,用于存储各个菜单,供员工选择。也就是说,基本上实现了菜单的管理功能。那么接下来要实现在线订餐的功能了。
为了简化功能,我们先不实现购物车的功能,只需要实现用户在设置订餐数量后,即可提交一个订单。午餐管理员就可以查看用户订餐列表了。
可以看出,现在需要下列“东西”:
一个表单:订餐表单,显示一个文本框,用于让用户输出订餐数量,以及一个提交按钮。
一个数据库:用于存放用户的订餐数据。
一个页面,午餐管理员可以查看员工的订餐情况。
除此之外,还需要显示一些提示信息等。
在平时做项目时,我喜欢迭代式的开发,简单的讲就是先开发主要功能,再逐步完善。一方面这样可以使客户能够清楚的看到进展,另一方面也能确保系统更为“扎实”。除此之外,还可以使程序员自己有一定的满足感,避免整天忙碌于开发却看不到效果,产和厌倦感。
下面按照上面的列的“东西”,一个一个的找解决方案。
订餐表单
这个表单上需要下列元素:
一个选择框,列表值为:1, 2, 3, 4, 5。我们假定一个员工最多只能订5份套餐。
一个提交按钮
这应该是最简单的表单了,下面看看怎么实现。
毫无疑问,需要使用传说中的Form API。Form API简称FAPI是Drupal中一个非常强大的表单生成函数。它包括表单生成、表单处理及结果显示等各个阶段的功能。其中最重要的几个函数为:drupal_get_form()
有一个钩子函数和form有关,不过大家要弄清它的用途:hook_form。这个函数是用于通过模块自定义content type时使用的,可以捕获create/edit节点时提交的表单。但这里要用的是drupal_get_form(), 用于生成一个表单。
首先创建一个生成表单元素的函数function buy_food_form(),然后使用drupal_get_form('buy_food_form')就可以输出表单了。除了生成表单外,还要对用户提交的表单进行处理。Drupal中,表单处理分为两步:
验证提交的表单数据
对数据进行处理
这两个步骤都转变为两个钩子函数:hook_form_validate和hook_form_submit。我们只需要将hook换成生成表单函数的前缀即可,如food_order_form_validate和food_order_form_submit。
由于需要自己写函数了,因此不可避免的需要自定义模块了。我们将订餐模块命名为Food Order Module。需要创建下面两个文件:
food_order.info
food_order.module
下面分析一些表单提示函数和处理函数。
OK,表单准备好了,该研究一下将表单放哪里了。由设计图看出,我们需要将表单放置在每个菜单页面上,这样用户在浏览到感兴趣的菜单时,就可以直接订餐了。那么如何将表单放置在菜单页面中呢?有两种方法:
修改node-food.tpl.php
生成Block,放置在node/*页面中
我更倾向于第二种方法,虽然第一种方法更为直接。本例中我们还是使用第二种方法,因为这样更遵循`Drupal的MVC模式,而且自定义模块的好处是可以根据需要开关模块。
数据表
我们需要使用数据库来存储哪些同事订了什么餐。首先要做的工作是创建一个数据表。等等,由于我们使用的是强大的Drupal,是不是不需要创建数据表也可以实现这样的功能呢。答案是:YES,但是,本例为了让读者练习使用自定义的数据表,因此不采用Drupal模块的解决方案。其实在Drupal中有个很有名的电子商务类模块——Ubercart。其实订餐这个业务和买商品本质是一样的,因此Ubercart也可以实现这样的功能,只不过有点重量级了。感兴趣的朋友们可以试试Ubercart是否可以完成同样的需求。
Drupal之所以说它是CMF(Content Management Framework),是因为一方面,它具有很好的层次结构,比如“数据库抽像层”,同时提供了很多方便的API——一系列的数据库操作函数,用起来还是相当方便的。使用Drupal的DAL,可以使我们不去关心数据库服务器配置及连接等细节,而且由于Drupal除了mysql外还支持pgsql,因此我们的程序还可以移植到pgsql上而无须更改数据库操作代码。而且,有望在不远的将来,Drupal可以使用MSSQL和Oracle等大型数据库。数据库抽像层的好处也就更为明显了。
数据表中主要字段有:
菜单号(nid)
用户ID(uid)
订餐数量(qty)
应付金额(money)
订餐时间(created)
订餐查看页面
最后,需要一个页面,让管理员可以查看当天有哪些人订餐了。当然也可以查看历史订餐信息,不过这个没有什么太大意义。因此在这个页面上只查看当天的订餐信息就可以了。
我们通过一个表格显示所有订餐的信息。Drupal的API中有一个theme_table的函数,可以生成表格,而且还可以自动生成排序字段,不过使用起来稍微有些复杂。但还是推荐大家使用。
由于我们是自己创建的订餐表,因此需要用到db_query。
$sql = “SELECT * FROM {food_order}”;
$result = db_query($sql);
while ($row = db_fetch_array($result)) { }
另外,还可以使用pager_query轻松实现分页。
下面总结一下,本文给出了实现“在线订餐”的基本解决方案,主要是自己创建数据表,并使用FAPI生成表单,用db_query等插入数据及显示数据。下一小节将给出源代码,供大家参考。
2009年3月2日星期一
使用sites文件夹灵活管理多站点配置
Drupal支持多站点共用一个Drupal程序,意味着我们可以通过在sites目录下创建以网站域名为名称的子文件夹。Drupal就会根据网站域名读取对应的配置。
举一个经常碰到的应用场景:
在发布了网站后,需要维护本地开发用的程序和网站发布程序之间的同步。一般情况下,生产服务器的数据库配置等信息与本地开发环境是不同的。如果只有一个配置文件的话,那么在同步网站程序和本地程序时,就需要手工过滤或更改配置文件。这时就可以利用Drupal支持多站点配置文件的特性,在其sites目录下创建一个localhost子目录,以及www.example.com的子目录。然后分别将settings.php放置于这两个文件夹,并更改为相应的配置。那么当对本地程序和服务器程序进行同步时,就不需要更改配置文件了。
2009年2月26日星期四
Disable user language模块介绍
在开启了Local模块后,Drupal即可以支持多语言界面了。同时,也使用户可以在Account中修改他所需要的语言界面——Language Settings。不过,在很多情况下,比如做国内的网站,并不需要用户选择“英文”界面,因为有很多情况下,界面中的文字是直接用中文写的,如果用户切换到英文界面,就会很“ugly”。当然,我们还是提倡大家尽量用t()写更“国际化”的界面。
这时,我们就需要DUL模块了。开启它后,它就将user/edit中的Language Settings部分去掉了,用户只能使用网站的默认语言。
DUL模块的下载地址为:http://drupalmodules.com/module/disable-user-language
2009年2月21日星期六
使用Drupal 6 Form API上传文件
file_save_upload($source, $validators = array(), $dest = FALSE, $replace = FILE_EXISTS_RENAME)下面对每个参数作简要说明:$source:自定义表单中,上传组件的名称。我在开发时,在这个参数上花费了不少时间,下面是手册中的解释:
$source A string specifying the name of the upload field to save.我开始一直把upload field看成了upload file,以为这个函数传递的是文件名,因此始终不能上传成功。最后去include/file.inc的源文件中读源码,才发现了这个问题。因此提醒大家,不要误以为传递的应是文件名。
$validators: 用于检查上传文件的回调函数数组,元素就是函数名。这样使用:array('validate_upload' => $arg),其中$arg是你要传递给自定义检查函数的参数。
$dest: 上传文件的最终存放地址。Drupal有一个file_directory_path函数,用于返回当前Drupal的文件目录,如sites/default/files。
$replace: 指明如果上传的文件与现有文件重名,是否进行覆盖。如果不覆盖,则由Drupal自动重命名为filename_0, filename_1这样的文件。
下面给一个具体的示例,这是在drupal.org 找到的一些代码,然后我自己测试通过了。在使用之前,需确保files目录可写。
function my_form()
{
$form['upload'] = array(
'#type' => 'file',
'#title' => t('Upload your file:'),
'#size' => 40,
);
$form['#attributes'] = array('enctype' => "multipart/form-data");
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function my_form_submit($form, &$form_state)
{
$dest = file_directory_path();
if($file = file_save_upload('upload', array(), $dest))
{
$a = t('The attached file was successfully uploaded');
drupal_set_message($a);
}
else
{
drupal_set_message(t('The attched file failed to upload. Please try again'));
}
return;
}
2009年2月20日星期五
使用Firefox的GreaseMoneky插件
GreaseMonkey插件主要是可以让浏览器的使用者自定义网站的样式,或执行javaScript脚本。这样,我只需创建一个js脚本(GM是以.user.js为结尾的文件),然后使用GreaseMonkey设置,将进入Blogger的编辑页面时载入,就可以了。我写的脚本如下:
function addGlobalStyle(css) {
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
}
addGlobalStyle('#richeditorframe { height:500px ! important; } #modebar, #richeditorframe, #richbars, #editarea
{ width: 1000px }');
感兴趣的朋友们可以试一试。
2009年2月5日星期四
Drupal论坛简介
Drupal的Forum模块是核心可选模块,开启Taxnomy和Comment模块后即可以使用。Drupal官方认为这个Forum像phpBB那样的message board。核心功能就是:
- 用户就某一主题进行讨论
- 把用户的讨论进行归档收集
客户甲:我需要一个简单的供用户交流的地方即可。论坛可以分为几个部分:产品讨论、使用交流和客户服务。嗯....只需要简单的发帖回帖应该就可以了。
客户乙:我们要打造全宇宙最酷最棒的论坛。论坛功能要炫!论坛版块要又多又全,用户互动性和可玩性要强,什么金币啊、等级啊、荣誉啊,一个都不能少!还可以互相买卖帖子,可以发不到一定等级就不能浏览那种帖子。积分功能要全,根据积分等级还要分什么虾米、大侠等,总之就是:炫!另外,由于用户至少同时在线100万,每个子论坛至少要支持10个以上的版主......
2009年1月25日星期日
方医生恭祝大家牛年快乐!
2009年1月17日星期六
让Drupal展示绚烂的图表-Open Flash Chart
Drupal项目实战-公司订餐系统(三)
上一节的进展为:
- 创建了Food的Content type
- 使用CCK创建了Food的相关字段
- 修改了node-food.tpl.php
目前,简单的菜单管理功能模块可以说基本上完成了,除了权限控制部分。我认为权限控制应该在所有系统功能完成后再统一考虑,目前还是先实现功能为主。那么接下来,就可以进入订餐功能模块的开发了。本文我们就开始订餐功能的设计和开发。
订餐功能模块分析
公司员工在浏览了菜单后,可以选择订购此午餐,同时设定购买数量。由于菜单是一个套餐,因此通常一个员工只会选择一种套餐。但是,此处我认为应该在一定程序上考虑系统的可扩展性,也就是说,应该考虑一个用户订两个或多个“套餐”的情况。因为很显然的是,员工小A想替小B和小C订餐的话,那么使用小A的帐户就需要同时订购三种不同的套餐。
其实此处就存在一个实际的业务模型和系统模型间的映射关系。如果只是从“一个员工中午只吃一种套餐”的常识来想,将每个“帐户”设定为“只允许订购一种套餐”的话,做成的系统就明显不适合使用了。这点也提醒做系统设计的朋友们要注意。
由于目前本系统只限于某公司员工内部使用,因此不存在需要填写送餐地址的信息。同时为了方便起见,暂时不考虑网上支付。这样问题就简化了。另外,用户在订餐时,通常会按照个人口味提出一些建议,因此系统还需要提供一个文本框,用于用户对订餐进行一些“补充说明”。
总结一下,订饭的流程如下:
- 浏览菜单并选择“订购”某套餐
- 设置订购数量
- 输入补充信息
- 查看购物车并确认生成订单
- 查看订单状态(已收到订单、已发货、收货确认)
如何升级Drupal 6
- 确定你的系统符合Drupal新版的要求。要求(Requirements)可以在http://drupal.org/requirements中查看。
- 备份所有的相关数据
- 检查自定义模块和主题的兼容性
- 确保你阅读了整个文件内容
- 数据库
- sites/all下面的所有文件
- sites/default/settings.php配置文件。如果是多站点,还需要备份每个站点settings.php文件。如sites/example.com/settings.php。
- .htaccess
- robots.txt
- 备份。备份所有能备份的东西。
- 获得超级管理员帐户。就是UserID = 1的用户。
- 将站点设置为off-line即下线状态,这样可以防止在升级时有用户访问。
- 将主题切换至默认主题——Garland。
- 关闭所有的第三方模块和自定义模块。
- 将Drupal自带的安装目录和程序全删除。这里指drupal根目录中除files、sites外其它的任何目录。
- 将新的Drupal程序包解压缩至相同位置。
- 设置好配置文件,如settings.php等。并且要确认是正确的。
- 关键的步骤:运行站点下的update.php,如http://www.example.com/update.php。如果你没权限运行,找到settings.php文件,将里面的$update_free_access设置为TRUE。然后在安装结束后再设置为FALSE。
- 运行update.php成功后,开启自定义和第三方模块modules。
- 再次运行update.php。
- 成功后,将站点设置为“上线on-line”。
- 更新结束。
2009年1月12日星期一
Drupal Views 2攻略-自定义View模板
网速快的朋友可去Youtube看,地址为:
2009年1月11日星期日
Drupal地心游记:神秘的羊皮纸
在Drupal中,index.php负责所有URL的解析和所有页面的生成工作。比如要访问增加内容的页面,它的URL是http://localhost/drupal/index.php?q=node/add;如果要访问管理页面,那就是index.php?q=admin。由此可见,index.php是整个Drupal系统的路由(route),用于接收URL请求,并跟据请求,调用不同的函数,最终生成整个页面。
即使我们开启了Clean URL,用简洁的方式(如http://localhost/drupal/admin来访问管理页面)访问页面,其原理只是利用Apache的Rewrite功能,将Clean URL转义为index.php?q={},调用index.php来生成页面。
2009年1月6日星期二
Drupal 缓存基础
2009年1月3日星期六
Drupal视频讲座第一辑—Views 2攻略

2008年12月31日星期三
再见,2008;你好,2009。
{
year2008.End();
Year year2009 = new Year(2009);
year2009.Start();
}
PHP:
<?php
unset($year2008);
/*
* TODO: Give $year2009 a meaningful value.
*/
$year2009 = "";
?>
2008年12月30日星期二
Drupal项目实战:公司员工订餐系统(二)
- 查看节点的变量
- 清空缓存(模块的)
- 生成测试数据(节点等)
- 开发节点类型的模板:node-content_type.tpl.php
- 开发评论的模板:comment.tpl.php
- 开发普通页面的模板:page.tpl.php
- 开发首页模板:page-front.tpl.php
- 整理CSS类别和区块
- 制作全站的CSS,写入style.css,或创建单独的样式表文件,在style.css中import.
- 为生产站点作CSS优化:如使用Drupal的CSS Aggregation将CSS文件整合为一个文件或重新设置每页加载的CSS文件。
| 原始页面 | |
第一次布局修改:
| |
| 第二次布局修改 加入样式 采用table作布局 |
相关函数讲解
2008年12月18日星期四
Drupal地心游记:开始
Read the f**king code.
此句出自Linux之父Linus大神之口,虽然有点“dirty”,不过一针见血。想要了解一个系统、程序或框架的实质,唯一的、最终极的方法,就是阅读源代码。就好像要分析人类,首先要从解剖入手。但是,众所周之,一个完整的程序,源代码行数甚多,而且源文件也很多,初步看去,肯定无从下手。这也是大家通常会遇到的问题。本系列就是想和大家一起来解决这个“问题”。
Drupal是一个优秀的开源CMS,优秀的框架。它的流行是一种趋势,也是一种必然。简洁、开放、易于扩展、生机勃勃,这些都是新时代优秀框架的必备品质。Druapl发展至今已经是第6个版本,而且Drupal 7也呼之欲出,可见其发展迅猛程度。而且还被评为2008年最佳开源CMS。看来各位不了解Drupal都会显得“过时”了。
得易于Drupal是PHP开发的,我们可以轻松的查看其源代码,了解其组成原理。本人最近也要潜心研究一下Drupal的本质,因此就将研究过程记录与此,并与大家分享。旨在引发大家的共同讨探。
结合分析操作系统的方法,我认为分析Drupal可以从其核心模块入手,探究它是如何管理“内容”的,然后再扩展到其它模块。除了分析代码外,我还想从“哲学”上解析一下Drupal。大家不要紧张,这个“哲学”的词,在国外很普通,不单指“哲学”这们学科。其实世界万物都有一种其运行的原理或机理存在,软件产品是人类智慧的产物,因此融合了开发者的思维方法和一些很抽像的东西。希望我们在探索的过程中,也能发现这些较高层次的智慧“碎片”。
小的时候看过一本书,叫《地心游记》,是著名科幻小说家凡尔纳的作品(此人还有另一作品比较有名:海底两万里),讲的是一群人探索地心的故事。我们就怀着对Drupal“地心”(Drupal Core)的好奇心和冒险精神,开始Drupal的地心之旅吧。





