Drupal项目实战:公司员工订餐系统 (一)
我们要做的是一个公司内部的员工订餐网站,它的主要功能是:
- 员工可以浏览各种菜的信息:为了简单,我们先假设可以浏览的是“套餐”
- 员工在选择好菜后,就可以下订单:订单中可以选择订菜的数量
- 饭店可以查看员工所下订单 :并根据订单进行送餐,订单的有效期是当日上午10:00 (假设我们订的是午餐)
- 菜单的主要属性:标题、说明、照片、价格
OK. 非常简单易懂,基本上三个需求 。这个系统中,主要的角色是:
- 公司员工
- 饭店
- 订餐管理员
- CCK、Views、Panels:这三个模块基本没什么悬念,任何一个网站几乎都会用到。Panels可能会损伤性能,不过它可以让我们避免陷入枯燥的CSS定位调试中。
- Image Field:用于添加Image的CCK Field
- Date:Date模块主要是一些日期相关的功能,也用于添加Date类型的CCK Field
- Vote API: 这个模块是用于评论时投票的,与FiveStar等模块连用,可以实现“小星星评分”,可爱又实用。
- Webform:在“下订单”时,我们有可能会用到,先列于此。
- 自定义模块:如果自己开发模块能够高效的解决问题,那么自定义模块也必不可少。
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作布局 |
|
Drupal默认的评论在最下方,我想把它放在页面的右侧,这样用户打开这个页面,无需浏览到底部,就可以看到最新的评论。cnbeta.com的形式也不错,它将“支持”者多的评论,放置在右侧。下面我们看看在D中怎样实现。
相关函数讲解
int strtotime ( string $time [, int $now ] )
array get_defined_vars ( void )
Drupal项目实战-公司订餐系统(三)
上一节的进展为:
- 创建了Food的Content type
- 使用CCK创建了Food的相关字段
- 修改了node-food.tpl.php
目前,简单的菜单管理功能模块可以说基本上完成了,除了权限控制部分。我认为权限控制应该在所有系统功能完成后再统一考虑,目前还是先实现功能为主。那么接下来,就可以进入订餐功能模块的开发了。本文我们就开始订餐功能的设计和开发。
订餐功能模块分析
公司员工在浏览了菜单后,可以选择订购此午餐,同时设定购买数量。由于菜单是一个套餐,因此通常一个员工只会选择一种套餐。但是,此处我认为应该在一定程序上考虑系统的可扩展性,也就是说,应该考虑一个用户订两个或多个“套餐”的情况。因为很显然的是,员工小A想替小B和小C订餐的话,那么使用小A的帐户就需要同时订购三种不同的套餐。
其实此处就存在一个实际的业务模型和系统模型间的映射关系。如果只是从“一个员工中午只吃一种套餐”的常识来想,将每个“帐户”设定为“只允许订购一种套餐”的话,做成的系统就明显不适合使用了。这点也提醒做系统设计的朋友们要注意。
由于目前本系统只限于某公司员工内部使用,因此不存在需要填写送餐地址的信息。同时为了方便起见,暂时不考虑网上支付。这样问题就简化了。另外,用户在订餐时,通常会按照个人口味提出一些建议,因此系统还需要提供一个文本框,用于用户对订餐进行一些“补充说明”。
总结一下,订饭的流程如下:
- 浏览菜单并选择“订购”某套餐
- 设置订购数量
- 输入补充信息
- 查看购物车并确认生成订单
- 查看订单状态(已收到订单、已发货、收货确认)
Drupal项目实战-公司订餐系统(四)
在上面的文章中,我们已经创建了一个Food节点类型,用于存储各个菜单,供员工选择。也就是说,基本上实现了菜单的管理功能。那么接下来要实现在线订餐的功能了。
为了简化功能,我们先不实现购物车的功能,只需要实现用户在设置订餐数量后,即可提交一个订单。午餐管理员就可以查看用户订餐列表了。
可以看出,现在需要下列“东西”:
-
一个表单:订餐表单,显示一个文本框,用于让用户输出订餐数量,以及一个提交按钮。
-
一个数据库:用于存放用户的订餐数据。
-
一个页面,午餐管理员可以查看员工的订餐情况。
除此之外,还需要显示一些提示信息等。
在平时做项目时,我喜欢迭代式的开发,简单的讲就是先开发主要功能,再逐步完善。一方面这样可以使客户能够清楚的看到进展,另一方面也能确保系统更为“扎实”。除此之外,还可以使程序员自己有一定的满足感,避免整天忙碌于开发却看不到效果,产和厌倦感。
下面按照上面的列的“东西”,一个一个的找解决方案。
订餐表单
这个表单上需要下列元素:
-
一个选择框,列表值为:1, 2, 3, 4, 5。我们假定一个员工最多只能订5份套餐。
-
一个提交按钮
这应该是最简单的表单了,下面看看怎么实现。
毫无疑问,需要使用传说中的Form API。Form API简称FAPI是Drupal中一个非常强大的表单生成函数。它包括表单生成、表单处理及结果显示等各个阶段的功能。其中最重要的几个函数为:
有一个钩子函数和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等插入数据及显示数据。下一小节将给出源代码,供大家参考。
drupal_get_form()
- [1] 敏捷开发:http://www.agilemanifesto.org/ :敏捷开发是RUP的一个扩展或精简,它有几个关键的实践用于指导软件开发过程。不过任何一种过程方法,都不可能适用于所有的项目,都需要经过我们自身的理解,并结合实际的项目情况而运用,要“以人为本”、“从群众中来、到群众中去”。
- [2] Best Practice:指最佳实践。