天天看點

Drupal項目實戰-公司訂餐系統

Drupal項目實戰:公司員工訂餐系統 (一)

簡單的需求

我們要做的是一個公司内部的員工訂餐網站,它的主要功能是:

  1. 員工可以浏覽各種菜的資訊:為了簡單,我們先假設可以浏覽的是“套餐”
  2. 員工在選擇好菜後,就可以下訂單:訂單中可以選擇訂菜的數量
  3. 飯店可以檢視員工所下訂單 :并根據訂單進行送餐,訂單的有效期是當日上午10:00 (假設我們訂的是午餐)
  4. 菜單的主要屬性:标題、說明、照片、價格

OK. 非常簡單易懂,基本上三個需求 。這個系統中,主要的角色是:

  • 公司員工
  • 飯店
  • 訂餐管理者

我們要做的就是實作這樣一個系統。首先快速做出原型,然後逐漸疊代,即采用靈活開發[1]方法。可以發揮同學的想像力,逐漸完善。

Drupal項目實戰-公司訂餐系統

圖1 員工午飯訂餐系統結構圖(使用者視角)

客戶 在了解了需求後,我們可以對系統的功能進行分析,以便進行技術架構的分析,進而估計出,要實作這樣一個系統,大概要多少成本。這是一個很現實的問題。在實際的項目中,客戶一般隻關心花多少錢來完成這樣一個項目,至于用哪種技術,用不用Drupal,其實他們并不關心。是以,某些開發者有時過多的向客戶介紹Drupal的優勢,其實是完全沒有必要的。隻需要讓客戶了解我們采用了“先進的”、“高效的”、“便于擴充”的技術架構就可以了。但是,對于開發者來說,技術架構是非常重要的,因為這樣我們才能準确的估計出是否能順利完成項目,以及其開發成本。

UML 我個人是比較主張使用UML的。因為UML的用例圖,狀态圖和時序圖等,可以很好很友善的對系統進行模組化,而且便于和世界各地的使用者交流。這一點很重要,因為如果我們的客戶和我們使用的不是同一種語言時,這種圖型就成為了很好的交流媒介。

分析

我們力求簡化開發過程,不必要的就直接省略。對于這個項目,我認為接下來應該分析如何用Drupal來實作。 首先,要找出系統中的“中繼資料”。因為Drupal是CMS,且核心就是Node。那麼分析系統時,首先就是找出系統中的“Node”,即“中繼資料”。從面向對像的角度看,就是“類”。我認為這是面向資料和面向對像分析的綜合運用。 菜單應該是系統中的“中繼資料”,因為所有的行為都是圍繞這個進行的。菜的主要屬性已經在需求中說明了,那麼我們可以馬上聯想到,“菜單”即是Node的子類,是Node的繼承,擴充Node的屬性(因為Node隻有标題和内容兩個内容屬性),就可以完成“菜單”的管理。我們把“菜單”類稱為Food。

除了Food,還有一個類是“訂單(Order)”。訂單用于記錄員工的訂餐情況。它也是一個“中繼資料(meta-data)”。那麼它是否也可以繼承Node類呢?我們知道,使用Drupal的一個原則,就是盡可能使用Drupal本身的子產品功能來完成業務需求。簡單的講,能少使用子產品就少使用子產品。現在有兩個第三方子產品可以實作電子商務的功能: e-Commerce 和 Ubercart 。

Drupal項目實戰-公司訂餐系統

前者曆史比較悠久,在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)的節點類型,增加幾個字段後,效果見下圖。由于屬基本操作,就不再贅述了。

Drupal項目實戰-公司訂餐系統

在完成菜單類型的建立後,發現預設的節點顯示頁面,實在是比較簡陋.這需要我們自己動手來完善一下.在開始之前,必須介紹一個很重要的子產品-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項目實戰-公司訂餐系統

對于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等,最後再進行“上色”。流程如下所示:

原始頁面
Drupal項目實戰-公司訂餐系統
第一次布局修改:
  • 分左中右三欄
  • 左側為圖像,中間為基本資訊,右側為評論。
Drupal項目實戰-公司訂餐系統

第二次布局修改

加入樣式

采用table作布局

Drupal項目實戰-公司訂餐系統

做成像cnbeta.com那樣的評論

Drupal預設的評論在最下方,我想把它放在頁面的右側,這樣使用者打開這個頁面,無需浏覽到底部,就可以看到最新的評論。cnbeta.com的形式也不錯,它将“支援”者多的評論,放置在右側。下面我們看看在D中怎樣實作。

Drupal項目實戰-公司訂餐系統

按正常思路,評論就應該在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 )

用途:此函數傳回目前頁面中所有可用的變量。調試佳品。

發貼者 方醫生 時間: 下午5:46 3 評論

Drupal項目實戰-公司訂餐系統

标簽: Drupal項目實戰-公司員工訂餐系統

Drupal項目實戰-公司訂餐系統(三)

上節回顧

上一節的進展為: 

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

目前,簡單的菜單管理功能子產品可以說基本上完成了,除了權限控制部分。我認為權限控制應該在所有系統功能完成後再統一考慮,目前還是先實作功能為主。那麼接下來,就可以進入訂餐功能子產品的開發了。本文我們就開始訂餐功能的設計和開發。

訂餐功能子產品分析

公司員工在浏覽了菜單後,可以選擇訂購此午餐,同時設定購買數量。由于菜單是一個套餐,是以通常一個員工隻會選擇一種套餐。但是,此處我認為應該在一定程式上考慮系統的可擴充性,也就是說,應該考慮一個使用者訂兩個或多個“套餐”的情況。因為很顯然的是,員工小A想替小B和小C訂餐的話,那麼使用小A的帳戶就需要同時訂購三種不同的套餐。

其實此處就存在一個實際的業務模型和系統模型間的映射關系。如果隻是從“一個員工中午隻吃一種套餐”的常識來想,将每個“帳戶”設定為“隻允許訂購一種套餐”的話,做成的系統就明顯不适合使用了。這點也提醒做系統設計的朋友們要注意。

由于目前本系統隻限于某公司員工内部使用,是以不存在需要填寫送餐位址的資訊。同時為了友善起見,暫時不考慮網上支付。這樣問題就簡化了。另外,使用者在訂餐時,通常會按照個人口味提出一些建議,是以系統還需要提供一個文本框,用于使用者對訂餐進行一些“補充說明”。

總結一下,訂飯的流程如下:

  1. 浏覽菜單并選擇“訂購”某套餐
  2. 設定訂購數量
  3. 輸入補充資訊
  4. 檢視購物車并确認生成訂單
  5. 檢視訂單狀态(已收到訂單、已發貨、收貨确認)

圖!圖!圖!

我認為任何語言的描述都不如頁面草圖來的直接。UML和簡潔的文字都不是和客戶交流的最好方式。看得見的頁面圖才是最有效的辦法。

Drupal項目實戰-公司訂餐系統
Drupal項目實戰-公司訂餐系統
Drupal項目實戰-公司訂餐系統
Drupal項目實戰-公司訂餐系統

上面幾張圖示範了在浏覽套餐菜單後,可直接訂餐的全部過程。 (未完待續)

Drupal項目實戰-公司訂餐系統(四)

在本系列上一個文章中,我畫了一些頁面草圖,用于展示網站原型。本文中将講解如何用Drpual來實作。

在上面的文章中,我們已經建立了一個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中,表單處理分為兩步:

  1. 驗證送出的表單資料
  2. 對資料進行處理

這兩個步驟都轉變為兩個鈎子函數: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()

發貼者 方醫生 時間: 上午10:25 3 評論

Drupal項目實戰-公司訂餐系統

标簽: Drupal項目實戰-公司員工訂餐系統

參考資料

  • [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