數(shù)據(jù)驗(yàn)證在web應(yīng)用中尤其顯得重要。下面來(lái)給大家介紹下禪道框架的數(shù)據(jù)驗(yàn)證機(jī)制。
mvc程序中,每一層都可以放驗(yàn)證規(guī)則。比如很多的表單驗(yàn)證,會(huì)自動(dòng)根據(jù)用戶的輸入進(jìn)行驗(yàn)證,然后給予提示。那么數(shù)據(jù)驗(yàn)證放在哪一層呢?這個(gè)問(wèn)題網(wǎng)絡(luò)上大家有很多的爭(zhēng)議。有的人主要放在view這一層,有的則主張放在control層。zentaoPHP選擇了model層。
為什么這樣做呢?因?yàn)閙odel層是底層,所有的數(shù)據(jù)操作,都要經(jīng)過(guò)model來(lái)進(jìn)行處理。那么只要在這一關(guān)把數(shù)據(jù)驗(yàn)證做好,就可以保證數(shù)據(jù)的準(zhǔn)確和安全。當(dāng)然,框架的用戶,可以同時(shí)在前端加上js的驗(yàn)證,和model層的驗(yàn)證不會(huì)沖突的。下面來(lái)看下如何使用禪道的數(shù)據(jù)過(guò)濾機(jī)制。
受php的filter機(jī)制啟發(fā),禪道的數(shù)據(jù)過(guò)濾分為兩個(gè)部分,一個(gè)是數(shù)據(jù)修正,一個(gè)是數(shù)據(jù)驗(yàn)證。首先是要對(duì)從客戶端傳遞過(guò)來(lái)的數(shù)據(jù)進(jìn)行修正,然后再對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)。
驗(yàn)證類是在lib/filter/filter.class.php里面定義的。
首先來(lái)看代碼:
$bug = fixer::input('post') ->add('openedBy', $this->app->user->account) ->add('openedDate', $now) ->setDefault('project,story,task', 0) ->setDefault('openedBuild', '') ->setIF($this->post->assignedTo != '', 'assignedDate', $now) ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) ->specialChars('title,steps,keyword') ->cleanInt('product, module, severity') ->join('openedBuild', ',') ->remove('files, labels') ->get();
首先,是調(diào)用fixer這個(gè)類的input方法,它的參數(shù)post表示是從$_POST這個(gè)變量中獲取數(shù)據(jù)。
緊接著的兩行add(),是向數(shù)據(jù)中增加兩個(gè)變量。
然后后面的兩行setDefault則是表示,當(dāng)這個(gè)變量沒(méi)有傳值的時(shí)候,設(shè)成默認(rèn)的值。
接下來(lái)是兩行setIF。setIF共有三個(gè)參數(shù),第一個(gè)是判斷條件,后面兩個(gè)分別是key和value。也就是當(dāng)條件為true的時(shí)候,設(shè)置$key = $value。
下面的spechialchars則表示對(duì)這三個(gè)字段進(jìn)行htmlspecialchars處理;cleanInt則將變量處理成int類型,join,則將openedBuild使用,連接起來(lái)。
后,還需要把兩個(gè)不需要的變量去掉,使用remove。
通過(guò)get方法就可以得到一個(gè)已經(jīng)經(jīng)過(guò)修改的完整的數(shù)據(jù)集合。這個(gè)集合已經(jīng)可以準(zhǔn)備入庫(kù)了。讓我們來(lái)看下數(shù)據(jù)是如何驗(yàn)證的。
$this->dao->insert(TABLE_BUG)->data($bug) ->autoCheck() ->batchCheck('id, name', 'notempty') ->exec();這句sql插入語(yǔ)句通過(guò)data方法,將修正過(guò)的數(shù)據(jù)傳遞給dao對(duì)象,然后通過(guò)autoCheck()對(duì)其進(jìn)行自動(dòng)檢查。autoCheck會(huì)根據(jù)數(shù)據(jù)庫(kù)里面字段的類型,長(zhǎng)度進(jìn)行判斷。如果類型不對(duì),或者長(zhǎng)度不對(duì),會(huì)自動(dòng)記錄錯(cuò)誤。然后后面調(diào)用了batchCheck()方法,對(duì)一批字段進(jìn)行非空的驗(yàn)證。
當(dāng)然也可以通過(guò)check()方法對(duì)單個(gè)字段進(jìn)行驗(yàn)證。驗(yàn)證的規(guī)則有很多,比如notempty, unique, email, account等等。
如果數(shù)據(jù)驗(yàn)證過(guò)程中沒(méi)有錯(cuò)誤,則執(zhí)行了exec()方法,將數(shù)據(jù)插入數(shù)據(jù)庫(kù)。
如果有錯(cuò)呢?exec()方法什么都不會(huì)執(zhí)行,但會(huì)記錄到錯(cuò)誤日志中??梢栽赾ontrol中里面判斷是否有錯(cuò)誤。
if(dao::isError()) die(js::error(dao::getError()));
如果有錯(cuò)誤,用js警告框的方式彈出,然后重置錯(cuò)誤日志。
數(shù)據(jù)修正方法:
cleanEmail: 將目標(biāo)字段處理為email encodeURL: 將目標(biāo)字段進(jìn)行urlencode cleanURL: 將目標(biāo)字段中不符合url標(biāo)準(zhǔn)的字符去掉。 cleanFloat: 將目標(biāo)字段處理為float類型。 cleanINT 將目標(biāo)字段處理為int類型。 specialChars: 對(duì)目標(biāo)字段使用htmlspecialchars處理。 stripTags: 去除目標(biāo)字段中的標(biāo)簽。 quote: 對(duì)目標(biāo)字段做quote處理。 setDefault: 對(duì)目標(biāo)字段設(shè)置默認(rèn)值。如果用戶有傳值,使用用戶傳的值。 setIF: 當(dāng)滿足某個(gè)條件的時(shí)候,對(duì)每個(gè)字段進(jìn)行設(shè)置。 setForce: 強(qiáng)制覆蓋某個(gè)字段的值。 remove: 刪掉某一個(gè)字段。 removeIF: 滿足某個(gè)條件的時(shí)候刪除某一個(gè)字段。 add: 添加某一個(gè)字段。 addIF: 當(dāng)滿足某個(gè)條件的時(shí)候,添加某一個(gè)字段。 join: 對(duì)目標(biāo)字段使用逗號(hào)連接起來(lái)。 callFunc: 使用自定義函數(shù)對(duì)數(shù)據(jù)進(jìn)行修正。
數(shù)據(jù)檢查方法:
bool: 目標(biāo)字段必須是布爾型。 int: 目標(biāo)字段必須是int類型。 float: 目標(biāo)字段必須是float類型。 email: 目標(biāo)字段必須是email類型。 url: 目標(biāo)字段必須是url 類型。 ip: 目標(biāo)字段必須是ip地址。有一個(gè)可選參數(shù):$range all|public|static|private date: 目標(biāo)字段必須是一個(gè)日期格式。 reg: 目標(biāo)字段必須滿足正則表達(dá)式。 length: 長(zhǎng)度要滿足指定的大小。 notEmpty: 目標(biāo)字段不能為空。 empty: 目標(biāo)字段必須為空。 account: 目標(biāo)字段必須是一個(gè)合法的用戶名。 equal: 目標(biāo)字段必須等于某一個(gè)值。 call: 調(diào)用用戶自己的檢查函數(shù)。
更多建議: