2006-02-11

PEAR::HTML_QuickForm與Smarty 的結合應用

Haohappy在《PHP & More》第三期的《PEAR::HTML_QuickForm入門》一文中說過要寫QuickForm和Smarty的結合應用,一直沒寫,今天看到PHPE論壇上有朋友在詢問,為自己的懶惰而慚愧。現在補上,希望對大家有點幫助。 在我看來,PEAR::HTML_QuickForm是個非常優秀的表單類庫,大大加快了開發速度,我現在的大多數專案都會用到。如果對PEAR::HTML_QuickForm不瞭解的朋友,建議先看這篇文章。


本文針對的讀者為有較豐富開發經驗的PHP程式師,要求讀者
1. 熟悉PEAR及其安裝和使用;
2. 熟悉HTML_QuickForm;
3. 理解範本的概念,熟悉Smarty範本引擎的使用。


在《PEAR::HTML_QuickForm入門》的表單的美化輸出一節中,提到了用QuickForm自帶的Form修飾方法來美化輸出。很明顯,這種方法顯得有點麻煩,而且讓程式師來美化網頁,有點難為我們了。 現在程式師和設計師的合作最常見的就是通過範本,所以如何把QuickForm和範本引擎相結合,這就是我們需要解決的問題。其實QuickForm可以和多種範本引擎相結合,如ITX, Sigma, Flexy, Smarty等,每種範本都有其優點和缺點,目前Smarty是最通用的範本引擎,所以我們把QuickForm和Smarty的結合作為重點來研究。

首先,給大家看看我們的最後效果:


這個例子非常簡單,只有一個Form,4個Input,只是用來講解QuickForm的使用。在實際開發中,我們經常遇到幾十個Input的情況。實際上,表單越複雜,就越顯出我們傳統的處理方式的低效,就越顯出QuickForm的強大。這一點,也許大家以後會體會到。


好,開始我們的QuickForm+Smarty之旅。
changPwd.php
assign('CSSDIR','./templates/admin');
$smarty->assign('title',':: Haohappy Test網站管理系統 ::');

//構建登錄表單
$form = new HTML_QuickForm('frmChgPwd', 'post');

//增加表單元素
$form->addElement('password', 'adminPwd', '','class = NameAndPwd');
$form->addElement('password', 'newPwd', '','class = NameAndPwd');
$form->addElement('password', 'newPwd2', '','class = NameAndPwd');
$form->addElement('submit', 'btnSubmit', '修改密碼','class = btnSubmit');

//增加驗證規則 會自動生成javascript變數,存入javascript驗證函數
$form->addRule('adminPwd','密碼不能為空!', 'required','','client'); 
$form->addRule('newPwd','新密碼不能為空!', 'required','','client'); 
$form->addRule('newPwd2','新密碼不能為空!', 'required','','client'); 
$form->addRule(array('newPwd','newPwd2'),"兩次輸入的密碼不同!!",'compare','','client');


if ($form->validate()) {
//如果表單數據正確,修改密碼
$form->process('changePwd');
}
else{

//否則顯示表單

// 建立renderer物件
$renderer =&new HTML_QuickForm_Renderer_ArraySmarty($smarty );    

// build the HTML for the form 生成表單的HTML代碼
$form->accept($renderer);

//assign array with form data 分配表單數據到陣列中
$smarty->assign('form_data', $renderer->toArray());
$smarty->catching = false;

// 調試
//echo "
";var_dump($renderer->toArray());echo "
"; $smarty->display("changePwd.tpl"); } //修改密碼 function changePwd(){} ?>


在代碼中,我們用$form->addElement()增添了4個表單元素,用$form->addRule()增加了4條驗證規則。怎麼樣,是不是很快捷方便? 以驗證兩個密碼是否相同的驗證規則為例,如果我們自己寫驗證規則,雖然快,但是代碼就會顯得臃腫和淩亂,由QuickForm來負責資料驗證,開發速度大大提高,而且代碼顯得很簡潔漂亮。僅用了一行代碼:
$form->addRule(array('newPwd','newPwd2'),"兩次輸入的密碼不同!!",'compare','','client');
關於QuickForm的好處,請參看《PEAR::HTML_QuickForm入門》,在此不再重複。

下面這行代碼就是我們將HTML_QuickForm與Smarty連接的橋樑:
$renderer =&new HTML_QuickForm_Renderer_ArraySmarty($smarty ); 

所謂renderer,就是用來負責顯示的,這裏我們把QuickForm的renderer指定為Smarty,我們就可以使用強大的Smarty範本引擎來格式化QuickForm的輸出了。

其他:

changePwd()是這個檔的核心操作函數,用來修改密碼。
$form->process('changePwd'); //這行代碼用來調用changePwd()

//echo "
";var_dump($renderer->toArray());echo "
";
這一行用來調試,我們隨時可以把$renderer中的所有變數列印出來,看看程式是否執行正確。

再看我們的範本,也很簡單:









{if $form_data.javascript}
{$form_data.javascript}
{/if}
































修改管理員密碼
現有管理員密碼
{$form_data.adminPwd.html}
新密碼
{$form_data.newPwd.html}
再次輸入新密碼
{$form_data.newPwd2.html}

{$form_data.btnSubmit.html}






這兩個簡單的檔,總共不到100行代碼,就完成了我們在文章開頭的效果。包含完整的表單數據驗證,處理過程。


另:使用QuickForm,可以很方便地實現顯示層和邏輯層的分離,因為處理的函數是完全獨立出來的。

例如說可以把


if ($form->validate()) {
//如果表單數據正確,修改密碼
$form->process('changePwd');
}


改裝成
if ($form->validate()) {

switch ($post_vars['action']) {

default:

case "changPwd":

$form->process('changePwd');

break;

case "Add":

$form->process('add');

break;



case "Update":

$form->process('update');

break;



case "Delete":

$form->process('delete');

break;

}


然後把changePwd,add,update,delete四個函數獨立到某個檔當中。這樣就可以根據頁面提交的action來調用不同的操作。


這個想法相對比較簡陋一些,如果你要用更強大的功能,還可以試試PEAR::HTML_QuickForm_Controller。HTML_QuickForm_Controller基於PageController設計模式,也就是用單個頁面來處理通過GET和POST傳遞而來的request和 action。這是個非常有意思的想法,但是這種開發模式不適合於新手,因為相對比較複雜。其作者也說:

HTML_QuickForm_Controller is not intended for PHP newbies. If you don't understand what classes are, if you have no prior experience with QuickForm, if you are a fan of copy-paste programming then this package is not for you.

The package is indeed complex, but so are the problems it is trying to solve. Try to rewrite any of the enclosed multipage form examples without using such a package and you'll see what we mean.

這部份暫不討論,這需要大家對MVC有一定瞭解,下次有機會再另寫文章。我自己目前的開發框架就是個MVC框架,覺得很順手,顯示部份就是交給Smarty+QuickForm來完成。希望有更多人關注和使用QuickForm,相信使用之後大家一定不會失望的:)

沒有留言: