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

2008年12月31日星期三

再见,2008;你好,2009。

C#:
{
year2008.End();
Year year2009 = new Year(2009);
year2009.Start();
}

PHP:
<?php
unset($year2008);
/*
* TODO: Give $year2009 a meaningful value.
*/
$year2009 = "";

?>

网站漫游指南

欢迎光临——方医生的Drupal频道!下面是网站漫游指南:
  • 右上角的“节目单”:最新内容和快捷链接
  • 右侧的“标签”:快速找到相关文章
  • 方医生讨论组:提问和互动
  • 右侧的“博客归档”:按发布月份寻找文章
  • 主要内容部分:最新发布的文章排在最前

2008年12月30日星期二

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 )
用途:此函数返回当前页面中所有可用的变量。调试佳品。

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的地心之旅吧。

2008年12月11日星期四

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“,那还需要大家一起共同探讨了。

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

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

2008年12月7日星期日

Drupal 6, Drupal 7正在逐渐变慢?

根据kbahey的 最新测试表明(http://2bits.com/articles/performance-benchmarking-drupal-512- drupal-66-and-drupal-7x-we-are-getting-slower.html),Drpual 7Drpual 6慢,Drupal 6Drupal 慢。本文的测试数据和测试结果均取自Kbahey的试验。

试验方法

实验采用了1024号新发布的Drupal 7,以及Drupal 6.6Drupal 5.12。首先在D5的站点上,使用Devel模块创建下列数据:

Users
5000

Nodes

4950

Comments

20000

Vocabularies

20000

Terms

1000

首页有30个节点的列表,没有自定义路径,一切使用原生的。下列模块被开启:system, block, color, comment, dblog, devel_generate, filter, help, menu, node, path, taxonomy, user, watchdog

然后,将D5站点分别升级至D6D7,再进行相同的测试,这样保证测试数据的一致性,使内容不会作为测试数据差异的原因。

Benchmarking 测试

我们使用2分钟内10用户的压力测试。所有的请求都成功完成(HTTP Code 200)。这个测试运行于三种条件下:

  1. 未开启缓存机制

  2. 开启普通的缓存机制

  3. 未开启APC[1]

  4. 开启APC

服务器环境是相同的:

  • Dual Core AMD 64 X2 2.2GHz

  • 2GB RAM

  • 160GB SATA disk

  • Ubuntu 8.04.1

  • Apache 2

  • MySQL 5.0

  • PHP 5.2.4.

Benchmarking 结果

版本

开启缓存

开启APC

Trans

Elap Time

Resp Time

Trans Rate

Concurrent

D5

N

N

1994

120.25

0.6

16.58

9.97

D6

N

N

1787

120.36

0.67

14.85

9.96

D7

N

N

1255

120.47

0.96

10.42

9.95

D5

N

Y

19481

119.78

0.06

162.64

9.98

D6

N

Y

15589

120.41

0.08

129.47

9.98

D7

N

Y

11418

120.26

0.11

94.94

9.98

D5

Y

N

6537

120.42

0.18

54.29

9.99

D6

Y

N

4706

120.56

0.27

39.03

9.97

D7

Y

N

2503

120.58

0.48

20.76

9.95

D5

Y

Y

50698

119.77

0.02

423.29

9.96

D6

Y

Y

46520

120.49

0.03

386.09

9.96

D7

Y

Y

34359

120.05

0.03

286.21

9.98

Trans: 完成的请求数量。

Elap Time: 完成这些数量的测试所花费的时间(秒)

Resp Time: 每个请求完成的时间(秒)

Trans Rate:每秒中完成的事务数,值越大越表现越佳。

Concurrent: 测试中同时在线人数,应该接近于10

分析

根据上面的统计数据,可以得出一些结论:

  • 如果未开启缓存和APC,那么D6D510.43%D7D629.83%

    • D7D537.15%

  • 如果开启了页面缓存,但未开启APCD6D520.39%D7D626.67%

    • D7D541.63%

  • 如果开启了APC但未开启页面缓存,D6D527.11%D7D646.81%

    • D7D561.76%

  • 如果同时开启APC以及页面缓存,D6D58.79%D7D625.87%

    • D7D532.38%

这些数据验证了:Drupal 5是目前Drupal版本中,在未安装其它任何贡献模块的情况下,是最快速的。而且当开启了Page Cache(页面缓存)和APC时,速度最快。