[2009/04/16]发布《Drupal项目实战-公司订餐系统(四)》本博客内容均为原创(Original),如有雷同,纯属巧合。转载请注明出处。同时欢迎学术探讨与批评。

2009年4月16日星期四

不使用Locale模块本地化Drupal

众所周知,在Drupal中要本地化,需要首先开启Locale模块,然后添加中文语言支持,再将中文包导入。其实还有一个很隐秘的地方可以放置翻译字符串,它在settings.php中。看下面的代码:
/**
* 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',
# );
如果你只需要翻译Drupal网站中的少部分字符串,那么就不需要开启Locale模块,再导入翻译包那样费劲了。在settings.php中,可以添加一些翻译字符串,Drupal在显示字符串时,会首先用这里面的字符串去进行替换。这样会省去很大一部分的资源消耗。比如:
$conf['locale_custom_strings_zh-hans'] = array(
'forum' => '讨论组',
'@count min' => '@count 分钟',
);
有两点需要注意:
  1. 要翻译中文,需要使用locale_custom_strings_zh-hans
  2. 要将settings.php存为utf-8格式
Enjoy!

Drupal项目实战-公司订餐系统(四)

在本系列上一个文章中,我画了一些页面草图,用于展示网站原型。本文中将讲解如何用Drpual来实现。

在上面的文章中,我们已经创建了一个Food节点类型,用于存储各个菜单,供员工选择。也就是说,基本上实现了菜单的管理功能。那么接下来要实现在线订餐的功能了。

为了简化功能,我们先不实现购物车的功能,只需要实现用户在设置订餐数量后,即可提交一个订单。午餐管理员就可以查看用户订餐列表了。

可以看出,现在需要下列“东西”:

  • 一个表单:订餐表单,显示一个文本框,用于让用户输出订餐数量,以及一个提交按钮。

  • 一个数据库:用于存放用户的订餐数据。

  • 一个页面,午餐管理员可以查看员工的订餐情况。

除此之外,还需要显示一些提示信息等。

在平时做项目时,我喜欢迭代式的开发,简单的讲就是先开发主要功能,再逐步完善。一方面这样可以使客户能够清楚的看到进展,另一方面也能确保系统更为“扎实”。除此之外,还可以使程序员自己有一定的满足感,避免整天忙碌于开发却看不到效果,产和厌倦感。

下面按照上面的列的“东西”,一个一个的找解决方案。

订餐表单

这个表单上需要下列元素:

  • 一个选择框,列表值为:1, 2, 3, 4, 5。我们假定一个员工最多只能订5份套餐。

  • 一个提交按钮

这应该是最简单的表单了,下面看看怎么实现。

毫无疑问,需要使用传说中的Form APIForm API简称FAPIDrupal中一个非常强大的表单生成函数。它包括表单生成、表单处理及结果显示等各个阶段的功能。其中最重要的几个函数为:

drupal_get_form()
有一个钩子函数和form有关,不过大家要弄清它的用途:hook_form。这个函数是用于通过模块自定义content type时使用的,可以捕获create/edit节点时提交的表单。但这里要用的是drupal_get_form(), 用于生成一个表单。

首先创建一个生成表单元素的函数function buy_food_form(),然后使用drupal_get_form('buy_food_form')就可以输出表单了。除了生成表单外,还要对用户提交的表单进行处理。Drupal中,表单处理分为两步:

  1. 验证提交的表单数据

  2. 对数据进行处理

这两个步骤都转变为两个钩子函数:hook_form_validatehook_form_submit。我们只需要将hook换成生成表单函数的前缀即可,如food_order_form_validatefood_order_form_submit

由于需要自己写函数了,因此不可避免的需要自定义模块了。我们将订餐模块命名为Food Order Module。需要创建下面两个文件:

  • food_order.info

  • food_order.module

下面分析一些表单提示函数和处理函数。

OK,表单准备好了,该研究一下将表单放哪里了。由设计图看出,我们需要将表单放置在每个菜单页面上,这样用户在浏览到感兴趣的菜单时,就可以直接订餐了。那么如何将表单放置在菜单页面中呢?有两种方法:

  • 修改node-food.tpl.php

  • 生成Block,放置在node/*页面中

我更倾向于第二种方法,虽然第一种方法更为直接。本例中我们还是使用第二种方法,因为这样更遵循`DrupalMVC模式,而且自定义模块的好处是可以根据需要开关模块。

数据表

我们需要使用数据库来存储哪些同事订了什么餐。首先要做的工作是创建一个数据表。等等,由于我们使用的是强大的Drupal,是不是不需要创建数据表也可以实现这样的功能呢。答案是:YES,但是,本例为了让读者练习使用自定义的数据表,因此不采用Drupal模块的解决方案。其实在Drupal中有个很有名的电子商务类模块——Ubercart。其实订餐这个业务和买商品本质是一样的,因此Ubercart也可以实现这样的功能,只不过有点重量级了。感兴趣的朋友们可以试试Ubercart是否可以完成同样的需求。

Drupal之所以说它是CMF(Content Management Framework),是因为一方面,它具有很好的层次结构,比如“数据库抽像层”,同时提供了很多方便的API——一系列的数据库操作函数,用起来还是相当方便的。使用DrupalDAL,可以使我们不去关心数据库服务器配置及连接等细节,而且由于Drupal除了mysql外还支持pgsql,因此我们的程序还可以移植到pgsql上而无须更改数据库操作代码。而且,有望在不远的将来,Drupal可以使用MSSQLOracle等大型数据库。数据库抽像层的好处也就更为明显了。

数据表中主要字段有:

  • 菜单号(nid)

  • 用户ID(uid)

  • 订餐数量(qty)

  • 应付金额(money

  • 订餐时间(created)

订餐查看页面

最后,需要一个页面,让管理员可以查看当天有哪些人订餐了。当然也可以查看历史订餐信息,不过这个没有什么太大意义。因此在这个页面上只查看当天的订餐信息就可以了。

我们通过一个表格显示所有订餐的信息。DrupalAPI中有一个theme_table的函数,可以生成表格,而且还可以自动生成排序字段,不过使用起来稍微有些复杂。但还是推荐大家使用。

由于我们是自己创建的订餐表,因此需要用到db_query

$sql = “SELECT * FROM {food_order}”;

$result = db_query($sql);

while ($row = db_fetch_array($result)) { }

另外,还可以使用pager_query轻松实现分页。

下面总结一下,本文给出了实现“在线订餐”的基本解决方案,主要是自己创建数据表,并使用FAPI生成表单,用db_query等插入数据及显示数据。下一小节将给出源代码,供大家参考。