现在的位置: 首页 > 综合 > 正文

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

2013年04月05日 ⁄ 综合 ⁄ 共 8481字 ⁄ 字号 评论关闭

Drupal项目实战:公司员工订餐系统 (一)

简单的需求
我们要做的是一个公司内部的员工订餐网站,它的主要功能是:

  1. 员工可以浏览各种菜的信息:为了简单,我们先假设可以浏览的是“套餐”
  2. 员工在选择好菜后,就可以下订单:订单中可以选择订菜的数量
  3. 饭店可以查看员工所下订单 :并根据订单进行送餐,订单的有效期是当日上午10:00 (假设我们订的是午餐)
  4. 菜单的主要属性:标题、说明、照片、价格

OK. 非常简单易懂,基本上三个需求 。这个系统中,主要的角色是:

  • 公司员工
  • 饭店
  • 订餐管理员
我们要做的就是实现这样一个系统。首先快速做出原型,然后逐步迭代,即采用敏捷开发[1]方法。可以发挥同学的想像力,逐步完善。
图1 员工午饭订餐系统结构图(用户视角)

客户
在了解了需求后,我们可以对系统的功能进行分析,以便进行技术架构的分析,进而估计出,要实现这样一个系统,大概要多少成本。这是一个很现实的问题。在实际的项目中,客户一般只关心花多少钱来完成这样一个项目,至于用哪种技术,用不用Drupal,其实他们并不关心。因此,某些开发者有时过多的向客户介绍Drupal的优势,其实是完全没有必要的。只需要让客户了解我们采用了“先进的”、“高效的”、“便于扩展”的技术架构就可以了。但是,对于开发者来说,技术框架是非常重要的,因为这样我们才能准确的估计出是否能顺利完成项目,以及其开发成本。

UML
我个人是比较主张使用UML的。因为UML的用例图,状态图和时序图等,可以很好很方便的对系统进行建模,而且便于和世界各地的用户交流。这一点很重要,因为如果我们的客户和我们使用的不是同一种语言时,这种图型就成为了很好的交流媒介。

分析
我们力求简化开发过程,不必要的就直接省略。对于这个项目,我认为接下来应该分析如何用Drupal来实现。
首先,要找出系统中的“元数据”。因为Drupal是CMS,且核心就是Node。那么分析系统时,首先就是找出系统中的“Node”,即“元数据”。从面向对像的角度看,就是“类”。我认为这是面向数据和面向对像分析的综合运用。
菜单应该是系统中的“元数据”,因为所有的行为都是围绕这个进行的。菜的主要属性已经在需求中说明了,那么我们可以马上联想到,“菜单”即是Node的子类,是Node的继承,扩展Node的属性(因为Node只有标题和内容两个内容属性),就可以完成“菜单”的管理。我们把“菜单”类称为Food。

除了Food,还有一个类是“订单(Order)”。订单用于记录员工的订餐情况。它也是一个“元数据(meta-data)”。那么它是否也可以继承Node类呢?我们知道,使用Drupal的一个原则,就是尽可能使用Drupal本身的模块功能来完成业务需求。简单的讲,能少使用模块就少使用模块。现在有两个第三方模块可以实现电子商务的功能:e-CommerceUbercart

前者历史比较悠久,在Drupal 5时代非常流行,不过进入Drupal 6时代就暂停开发了。听说最近又重新开始开发了,估计作者前一段时间持观望态度。Ubercart是后起之秀,它也是以“商品”为主的电子商务网站的解决方案。而且Ubercart也于最近推出了Drupal 6的beta版本。我没有对这两个插件作过横向对比,刚好我们借这个实战项目,也可以进行一下实验。不过,在使用这两个模块之前,我想先使用“纯Drupal”来实现我们的功能(尝试),如果能实现,那么效率应该是比较高的,而且更简单。

预计要使用的模块
有人说,Drupal开发就是“拼模块”,此话有一定道理。而且大多数人在用Drupal开发时,马上头脑中就无数个模块翻腾。其实这不是一个很好的现象,很容易在还没真正弄清楚需求前就陷入了技术误区。当然,我们还是需要在开始前设想一下需要使用哪些模块,因为这样可以提前下载下来,做下尝试。不过我更倾向于:边做边找的模式。也许这不是最佳实践,不过对于比较小的项目还是很有效率的。
  • CCK、Views、Panels:这三个模块基本没什么悬念,任何一个网站几乎都会用到。Panels可能会损伤性能,不过它可以让我们避免陷入枯燥的CSS定位调试中。
  • Image Field:用于添加Image的CCK Field
  • Date:Date模块主要是一些日期相关的功能,也用于添加Date类型的CCK Field
  • Vote API: 这个模块是用于评论时投票的,与FiveStar等模块连用,可以实现“小星星评分”,可爱又实用。
  • Webform:在“下订单”时,我们有可能会用到,先列于此。
  • 自定义模块:如果自己开发模块能够高效的解决问题,那么自定义模块也必不可少。
主题模板
Drupal中的主题模板(Theme)是表示层的术语,除了样式、色彩等,我们还要对内容的显示布局。默认的节点显示页面只适合简单的内容类型,如果我们使用了CCK扩展节点字段的话,那么就需要自定义模板文件了。本项目对网站风格的要求是简洁,同时为了开发方便考虑,先使用Garland(Drupal默认模板)主题,然后再进行定制。

工具
我喜欢使用EditPlus作为开发PHP的工具,然后配以Firefox+Firebug和IE+Developer Tools(或IE8)进行调试。在工具方面,仁者见仁,智者见智,没有好坏之分,只有熟练与否。Choose whatever you like.
同时,我发现微软的Visual Web Developer Express是一个非常不错的编辑器,尤其是网页开发,可用于页面设计,有兴趣的朋友们也可以试一试。

小结
本文叙述了项目的需求,并进行了分析和设计。采用Drupal的开发与普通的软件开发还是有区别的,因为我们是“站在Drupal的肩膀”上,因此对软件开发过程可以做一定的“剪裁”。至于我的方法是不是“Best Practice“,那还需要大家一起共同探讨了。

详细的开发流程从第二篇开始。

 

 

Drupal项目实战:公司员工订餐系统(二)

创建菜单节点

首先创建菜单(Food)的节点类型,增加几个字段后,效果见下图。由于属基本操作,就不再赘述了。
在完成菜单类型的创建后,发现默认的节点显示页面,实在是比较简陋.这需要我们自己动手来完善一下.在开始之前,必须介绍一个很重要的模块-Devel(http://drupal.org/project/devel).此模块为开发者必备,主要功能有:
  • 查看节点的变量
  • 清空缓存(模块的)
  • 生成测试数据(节点等)
我常用的是这几个,对于D6,它还可以调试主题模板,比较有效.不过,这个模块有时会用其它模块的Javascript脚本有冲突,目前还不太明确与哪些模块有冲突.如果朋友们在调试Drupal时发现莫名其妙的JS问题,可以考虑先关闭Devel模块,然后再试.

开发主题,当然还需要能方便查看和动态更改CSS的浏览器支持.Firefox+Firebug组合当仁不让成为现时的首选.不过目前,IE8和Chrome也正努力赶上.IE8中按F12可以调出和IE Developer Tools相似的HTML,CSS代码调试框,基本上Firebug功能类似.Chrome目前可以定位HTML页面元素,以及查看其CSS样式,不过还不能即时修改.选择哪个就看大家自己的喜好了.一般情况下,我们都要调试Firefox和IE下的兼容性.尤其是Div+CSS的布局,如果没有很高的技巧,确实需要调试很长时间。

创建菜单显示模板
在开始创建之前,当然要进行设计.我们的项目目前没"网页设计",那我们就直接挑一个差不多的作参考吧。如果你的项目组中有美工人员,这部分应该交给他/她去做了。对于Drupal页面的设计,我的意见是:尽量符合Drupal默认的页面布局,这样交给Drupal开发者时,只需要做少量修改即可。否则就需要花很多时间在主题和模板开发上.毕竟CSS技巧高的又懂Drupal的同志,还是不大容易找到的。
我看中了一个国外网站的"菜单"信息的显示页面,分享一下:http://www.foodnetwork.com/recipes/paula-deen/christmas-ham-recipe/index.html.截图如下。
对于Drupal项目,我认为首先应该开发针对不同的节点类型的页面的显示模板,即:node-content_type.tpl.php。它是显示的模板,它包含节点的各个元素的显示方式的设定(如标题、内容、以及用CCK生成的字段等),但不对整个页面的布局进行设定。此处需要提一个需要注意的问题:通过Devel的"Dev load"查看的变量,并不是在node.tpl.php中直接可用的变量。它显示的是通过node_load函数得到的$node节点,与node.tpl.php中的$node节点还是有区别的。同时,大家在使用节点变量时,也可以参考一下$node->content变量中的内容,它是经过Drupal处理后的HTML内容。

关于Drupal主题模板开发的顺序,下面是我的看法:
  1. 开发节点类型的模板:node-content_type.tpl.php
  2. 开发评论的模板:comment.tpl.php
  3. 开发普通页面的模板:page.tpl.php
  4. 开发首页模板:page-front.tpl.php
  5. 整理CSS类别和区块
  6. 制作全站的CSS,写入style.css,或创建单独的样式表文件,在style.css中import.
  7. 为生产站点作CSS优化:如使用Drupal的CSS Aggregation将CSS文件整合为一个文件或重新设置每页加载的CSS文件。

我喜欢的开发顺序是:先把所有的HTML写出,然后创建好每个CSS类和ID等,最后再进行“上色”。流程如下所示:
原始页面
第一次布局修改:

  • 分左中右三栏
  • 左侧为图像,中间为基本信息,右侧为评论。
第二次布局修改
加入样式

采用table作布局

做成像cnbeta.com那样的评论

Drupal默认的评论在最下方,我想把它放在页面的右侧,这样用户打开这个页面,无需浏览到底部,就可以看到最新的评论。cnbeta.com的形式也不错,它将“支持”者多的评论,放置在右侧。下面我们看看在D中怎样实现。

按正常思路,评论就应该在page.tpl.php中设置。但是,在page.tpl.php中只能找到$content变量。因此,将评论更换显示位置就显得有点“棘手”了。我目前的解决方法是:使用Views创建某个节点的评论列表,然后创建自定义模块,调用views_build_view函数,将列表以区块的形式,放置在右侧区域。那么,这部分应该以区块形式存在,放置在right区域,也无须对node.tpl.php进行修改了。
(未完待续)


相关函数讲解
theme_image($path, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE)
用途:显示图像,生成IMG标签,同时可以设置style属性——通过设置$attributes数组。
参数解析:
$path:图像路径。如本例中,如果为节点创建了Image Field,那么可以将$field_food_pic[0]['filepath']作为参数传入。
$attributes:用于设置HTML标签的style属性。像这样使用即可——array('weight' => '200px', 'height' => '100px')。
$getsize:如果设置为TRUE,那么将会按照图像文件的实际长和宽来显示图像,通过$attributes设置的自定义长和宽就会失效。

int strtotime ( string $time [, int $now ] )

用途:将任何英文文本的日期时间描述解析为 Unix 时间戳。使用Drupal的Date field得到的日期是ISO日期格式的,如2008-10-20T10:20:20。大家可以发现多了一个“T”,因此我们需要先将这个日期转化为UNIX时间戳,然后再转换为适当的日期格式。

array get_defined_vars ( void )

用途:此函数返回当前页面中所有可用的变量。调试佳品。

 

 

 

 

 

 

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

上节回顾

上一节的进展为: 

  • 创建了Food的Content type
  • 使用CCK创建了Food的相关字段
  • 修改了node-food.tpl.php

目前,简单的菜单管理功能模块可以说基本上完成了,除了权限控制部分。我认为权限控制应该在所有系统功能完成后再统一考虑,目前还是先实现功能为主。那么接下来,就可以进入订餐功能模块的开发了。本文我们就开始订餐功能的设计和开发。

订餐功能模块分析

公司员工在浏览了菜单后,可以选择订购此午餐,同时设定购买数量。由于菜单是一个套餐,因此通常一个员工只会选择一种套餐。但是,此处我认为应该在一定程序上考虑系统的可扩展性,也就是说,应该考虑一个用户订两个或多个“套餐”的情况。因为很显然的是,员工小A想替小B和小C订餐的话,那么使用小A的帐户就需要同时订购三种不同的套餐。

其实此处就存在一个实际的业务模型和系统模型间的映射关系。如果只是从“一个员工中午只吃一种套餐”的常识来想,将每个“帐户”设定为“只允许订购一种套餐”的话,做成的系统就明显不适合使用了。这点也提醒做系统设计的朋友们要注意。

由于目前本系统只限于某公司员工内部使用,因此不存在需要填写送餐地址的信息。同时为了方便起见,暂时不考虑网上支付。这样问题就简化了。另外,用户在订餐时,通常会按照个人口味提出一些建议,因此系统还需要提供一个文本框,用于用户对订餐进行一些“补充说明”。

总结一下,订饭的流程如下:

  1. 浏览菜单并选择“订购”某套餐
  2. 设置订购数量
  3. 输入补充信息
  4. 查看购物车并确认生成订单
  5. 查看订单状态(已收到订单、已发货、收货确认)

图!图!图!

我认为任何语言的描述都不如页面草图来的直接。UML和简洁的文字都不是和客户交流的最好方式。看得见的页面图才是最有效的办法。

上面几张图演示了在浏览套餐菜单后,可直接订餐的全部过程。
(未完待续)

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

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

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

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

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

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

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

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

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

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

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

订餐表单

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

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

  • 一个提交按钮

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

毫无疑问,需要使用传说中的Form APIForm API简称FAPIDrupal中一个非常强大的表单生成函数。它包括表单生成、表单处理及结果显示等各个阶段的功能。其中最重要的几个函数为:
有一个钩子函数和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等插入数据及显示数据。下一小节将给出源代码,供大家参考。

drupal_get_form()

 


参考资料
  • [1] 敏捷开发:http://www.agilemanifesto.org/ :敏捷开发是RUP的一个扩展或精简,它有几个关键的实践用于指导软件开发过程。不过任何一种过程方法,都不可能适用于所有的项目,都需要经过我们自身的理解,并结合实际的项目情况而运用,要“以人为本”、“从群众中来、到群众中去”。
  • [2] Best Practice:指最佳实践。

 

转载:http://doctor-fang.blogspot.com/search/label/Drupal%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98-%E5%85%AC%E5%8F%B8%E5%91%98%E5%B7%A5%E8%AE%A2%E9%A4%90%E7%B3%BB%E7%BB%9F


抱歉!评论已关闭.