版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
對于用戶輸入的任何數(shù)據,如從表單提交中獲取的數(shù)據,即使不考慮惡意企圖,程序員也必須做最壞的打算。因此,程序員總是要面對檢查數(shù)據是否正確及可用的問題。本章會展示一些在日常工作中能夠發(fā)揮作用的算法與函數(shù)。在檢查數(shù)據正確性時,分解為兩個步驟將會帶來很大便利:一是將輸入數(shù)據標準化,二是檢查標準化之后的數(shù)據。輸入數(shù)據的''標準化"就是將得到的數(shù)據調整為統(tǒng)一或是標準格式。各種信息本來都會有一些不同的表達方式,但對于特定的應用程序來說,它們都需要被轉化為某種標準格式。之后,我們就可以對標準格式的數(shù)據應用有效性規(guī)則,從而確定輸入的數(shù)據是可用的。將數(shù)據檢驗分為兩個步驟可以使過程更加簡單和靈活。標準化過程只關心格式問題,程序可以讓用戶以更自由的方式提供信息,從而具有更高的用戶友好度。當輸入信息被標準化之后,檢查過程就簡單多了,因為信息格式是已知的。當然,凡事皆有例外,有些場合就不適合這種標準化之后進行檢驗的方法。例如,有時表單輸入是數(shù)據檢驗的組成部分,這樣就打破了兩個步驟的次序;如果輸入信息不具有期望的格式,它就會立即變得無效。下面這些范例都假設用戶被要求以某種格式提供信息,而且沒有其他程序對用戶輸入進行處理,范例中得到的數(shù)據是“原始的”。快速提示0檢查變量是否是數(shù)字或數(shù)字式字符串:$success=is_numeric($variable);如果變量是數(shù)字,或者是包含數(shù)字及符號、小數(shù)點、指數(shù)的字符串,這個函數(shù)就會返回True。完整文檔:/is_numeric。0檢查字符串是否只包含字母數(shù)字:$success=ctype_aInum($string);如果字符串里只包含字母或數(shù)字,這個函數(shù)就會返回True。完整文檔:/ctype_alnum。0檢查字符串是否只包含字母:$success=ctype_alpha($string);如果字符串里只包含字母“a”到“z"(不分大小寫),函數(shù)就會返回True。
完整文檔:/ctype_alpha。0檢查字符串里是否只包含數(shù)字:$success=ctype_digit($string);如果字符串里只包含字符“0"到“9",函數(shù)就會返回True。注意,不允許有小數(shù)點。完整文檔:/ctype_digit。0檢查字符串里是否只包含十六進制數(shù)字:$success=ctype_xdigit($string);允許的字符是“0”到“9"和“a”到“f"(無論大小寫)。完整文檔:/ctype_xdigit。0檢查字符串是否全是大寫的或全是小寫的:$success=ctype_upper($string);$success=ctype」ower($string);如果字符串包含不同的大小寫,函數(shù)就會返回False。完整文檔:/ctype_upper和/ctype_lower。0強制變量為指定類型:$success=settype($variable,$type);PHP利用其內部類型轉化將變量強制為指定類型。如果轉化不能實現(xiàn),函數(shù)會返回False。完整文檔:/settype。0使用類型轉化將變量解釋為特定類型:$result=(typekeyword)$variable;PHP將變量值從原始類型轉化為typekeyword指定的類型。完整文檔:/manual/language.types.type-juggling.php。11?1電話號碼本例中處理的電話號碼是美國使用的標準格式,它包含三位區(qū)號,隨后是三位局號,最后是四位數(shù)字。不幸的是,顯示(及輸入)這些數(shù)字的格式有很多種,如(999)555-0100、(999)555-0100、9995550100、999.555.0100和999-555-0
100。程序清單11.1.1可以接收上述(及其他)格式的數(shù)字,并且把它們標準化為最后一種形式,因為這便于計算機進行后續(xù)處理。在檢驗電話號碼時,除了確定它包含適當數(shù)量的數(shù)字之外,還有其他一些規(guī)則。例如,如果局號是555,那么后四位數(shù)字就不能在0100?0199之間,因為它們是被保留的。另外,區(qū)號不能以0或1開頭,并且第二個數(shù)字不能為9。根據這些規(guī)則,我們就得到了如程序清單11.1.1所示的函數(shù)。程序清單11.1.1電話號碼函數(shù)庫<?php//AfunctionthatwillacceptUSphonenumbers,inmosteveryformat//andstandardizethemtoxxx-xxx-xxxxformat.functionstandardize_phone($phone){//First,removeallnon-digitsfromthestring$p=preg_replace('/[人0-9]/','',$phone);//Now,breakitintoitsappropriatepartsandinsertdashes.returnsubstr($p,0,3).'-'.substr($p,3,3).'-'.substr($p,6);}//Afunctiontocheckforphonenumbervalidity//Itrequiresastandardizednumberfunctionvalidate_phone($phone){//Firstsplitthenumberinto3parts:$parts=explode('-',$phone);//Ifthemiddleis'555'if($parts[1]=='555'){//Invalidifthefinalpartisbetween0100and0199if(($parts[2]>=100)&&($parts[2]<200)){returnfalse;
//Invalidifthefirstdigitoftheareacodeis0or1if($parts[0]<200){returnfalse;}//Invalidiftheseconddigitoftheareacode,is9if($parts[0]{l}=='9'){returnfalse;}//Checkthatthelastnumberhas4characters:if(strlen($parts[2])!=4){returnfalse;}//Otherwise,wemadeit,it'svalid.returntrue;}//Standardize&validatesomephonenumbers:$phones=array('(108)355-4688','354-555-0103','294.423.8437','301867-5309','424-726739','829-56628426');foreach($phonesas$num){$st=standardize_phone($num);$valid=validate_phone($st);$output=$valid?'Valid':'Invalid';echo"<p>{$st}-{$output}</p>\n";}?>上述這些函數(shù)不允許電話號碼以1開頭,而有時人們確實會這樣輸入電話號碼(因為美國的國家區(qū)號就是1)。如果想允許用戶這樣輸入,只需要很簡單的
修改。最簡單的方式是在標準化程序中刪除號碼前面的1就可以了,因為國內區(qū)號是不能以1開始的。11?2郵政編碼美國的郵政編碼格式很簡單,易于實現(xiàn)標準化和檢驗。其格式是5個數(shù)字,后面還可能有一個破折號及4個數(shù)字。雖然這種格式很簡單,但判斷輸入的郵政編碼是否實際存在還是有一定困難的,基本方法就是查看當前有效編碼列表,而這些列表必須從美國郵政局才能得到。因此,程序清單11.2.1里的郵政編碼處理庫只實現(xiàn)了格式標準化及檢驗。程序清單11.2.1郵政編碼函數(shù)庫<?php//AfunctionthatwillacceptUSzipcodes//andstandardizethemtoxxxxx-xxxxformat.functionstandardize_zip($input){//First,removeallnon-digitsfromthestring$digits=preg_replace('/[人0-9]/','',$input);//Grabthefirstfivedigits:$ret=substr($digits,0,5);//Iftherearemorethan5,thenincludetherestafteradashif(strlen($digits)>5){$ret.='-'.substr($digits,5);}return$ret;}//Afunctiontocheckforzipcodevalidity//Itmusthavebeenstandardizedfirst.functionvalidate_zip($input){
//Firstsplitthenumberinto2parts:$parts=exploded-',$input);//Ifthefirstpartisnot5digits-Invalidif(strlen($parts[0])!=5){returnfalse;}//Ifthesecondpartexists,andisnot4digits-Invalidif(isset($parts[1])&&(strlen($parts[l])!=4)){returnfalse;}//Otherwise,wemadeit,it'svalid.returntrue;}//Standardize&validatesomezips:$zips=array('21771','7177','x23456','12345-6789','1313122','14142-77743','21705-123','2177-1234','1-1','7.42');foreach($zipsas$num){$st=standardize_zip($num);$valid=validate_zip($st);$output=$valid?'Valid':'Invalid';echo"<p>{$st}-{$output}</p>\n";?>11?3社會保障號(SSN)在美國,每個人都被分配一個“社會保障號(SSN)”,它在很多場合都成為核查身份的手段,因此經常是表單上的必填字段。它總是由3位數(shù)字開始,接
是2位數(shù)字,接著又是4位數(shù)字。在顯示這個號碼時,三個部分之間通常以破折號分隔,但有時人們會忘記。在檢驗時還可以使用更多的規(guī)則。這三個部分之中任意一個部分都不能全是0。目前,前三位數(shù)字(區(qū)號)不能比772大,因為那些數(shù)字還沒有被分配。當然,在新的號碼被分配之后,腳本就要做相應的修改。程序清單11.3.1展示了SSN標準化及檢驗例程。程序清單11.3.1社會保障號函數(shù)庫<?php//AfunctionthatwillacceptUSSSNs//andstandardizethemtoxxx-xx-xxxxformat.functionstandardize_ssn($ssn){//First,removeallnon-digitsfromthestring$s=preg_replace('/[人0-9]/','',$ssn);//Now,breakitintoit'sappropriatepartsandinsertdashes.returnsubstr($s,0,3).'-'.substr($s,3,2).'-'.substr($s,5);}//AfunctiontocheckforSSNvalidity,requiresastandardizednumberfunctionvalidate_ssn($ssn){//Firstsplitthenumberinto3parts:$parts=exploded-',$ssn);//Ifanypartisall0's-Invalidforeach($partsas$p){if($p==0){returnfalse;}}//Ifthefirstpartisgreaterthan772(Mayneedupdatedinfuture)if($parts[0]>772){
returnfalse;//Finally,ifthefinalpartisnot4characters,itisinvalidif(strlen($parts[2])!=4){returnfalse;}//Otherwise,wemadeit,it'svalid.returntrue;}//Standardize&validatesomeSSN:$ssn=array('774354688','354-00-0103','123456789','Hello');foreach($ssnas$num){$st=standardize_ssn($num);$valid=validate_ssn($st);$output=$valid?'Valid':'Invalid';echo"<p>{$st}-{$output}</p>\n";}?>如果需要,可以通過訪問美國社會保障管理局站點(/)來進一步嚴格地檢查SSN的有效性,那里有當前有效區(qū)號的完整列表,還有每個區(qū)號里已經分配的前兩位數(shù)字(遵循一種奇怪的分配方案)。這個列表每月更新一次,因此我們可以編寫腳本來讀取這個文件,解析其中的數(shù)據,從而建立真實有效的SSN查詢表。11.4數(shù)字在處理數(shù)字時,如貨幣金額,實際上并沒有通用的檢驗方式,而是要根據特定輸入信息檢查數(shù)據是否在有效范圍之內。不過我們可以創(chuàng)建一個函數(shù)來標準化得到的任何數(shù)值,所使用的格式滿足大多數(shù)數(shù)據庫對數(shù)值格式的要求,也就是說
數(shù)字之間沒有空格或逗號,負數(shù)值前面會有一個負號。另外,利用可選參數(shù)指定保留的小數(shù)位,自動進行四舍五入的操作。PHP能夠根據需要自動把字符串轉化為數(shù)值,但逗號、空格和其他一些因素經常會影響這種轉化。程序清單11.4.1解決了這些問題,從而得到有效的數(shù)值。程序清單11.4.1通用數(shù)值檢驗函數(shù)庫<?php//Afunctionthatwillacceptandcleanupnumberstringsfunctionstandardize_number($num,$precision=false){//First,removeallnon-digits,periods,and-signsfromthestring$num=preg_replace('/[人-.0-9]/','',$num);//Nowremoveany」sthatareinthemiddleofthestring:$num=preg_replace('/(?<=.)-/','',$num);//WenowhaveavalidstringthatPHPwillproperlyconsideranumber.//Ifaprecisionwasaskedfor,roundaccordingly:if($precision!==false){$num=round($num,$precision);}return$num;}//Standardizesomenumberstrings:$nums=array('123.4643','HelloIbought42flowersforyou.','-344-345.424','+544,342.566');foreach($numsas$num){$st=standardize_number($num,2);echo"<p>{$num}={$st}</p>\n";}?>
11?5信用卡號碼商業(yè)站點需要處理信用卡號碼。信用卡公司已經在卡號里建立了校驗體系。在把信用卡號碼標準化為不包含空格的數(shù)字字符串之后,可以進行兩方面的檢驗。首先,不同信用卡公司遵循特定的編號規(guī)則。nVisa:以4開頭,共有13位或16位數(shù)字。nMasterCard:以51?56開頭,共有16位數(shù)字。nAmericanExpress:以34或37開頭,共有15位數(shù)字。nDiscover:以6011開頭,共有16位數(shù)字。另外,所有卡號還要遵循稱為“Mod10”的算法,它可以用來判斷某個號碼是否屬于有效的信用卡號碼。它的工作方式是這樣的:首先顛倒數(shù)字的次序,接著每隔一個數(shù)字把數(shù)字乘以2,然后把所有的數(shù)字加起來;但如果相乘結果大于等于10,就要把這個結果的個位和十位的數(shù)字加起來。例如數(shù)字7,乘以2以后是14,所以它對應的數(shù)字應該是1+4=5。在所有數(shù)字相加之后,其結果應該能夠被10整除。上述這些規(guī)則都寫入了程序清單11.5.1包含的函數(shù)里。程序清單11.5.1信用卡號碼函數(shù)庫<?php//AfunctionthatwillacceptandcleanupCCnumbersfunctionstandardize_credit($num){//Removeallnon-digitsfromthestringreturnpreg_replace('/[人0-9]/','',$num);}//AfunctiontocheckthevalidityofaCCnumber//Itmustbeprovidedwiththenumberitself,aswellas//acharacterspecifyingthetypeofCC://m=Mastercard,v=Visa,d=Discover,a=AmericanExpressfunctionvalidate_credit($num,$type){
//FirstperformtheCCspecifictests://Storeafewevaluationswewillneedoften:$len=strlen($num);$d2=substr($num,0,2);//IfVisamuststartwitha4,andbe13or16digitslong:if((($type=='v')&&(($num{0}!=4)||!(($len==13)||($len==16))))||//IfMastercard,startwith51-56,andbe16digitslong:(($type=='m')&&(($d2<51)||($d2>56)||($len!=16)))||//IfAmericanExpress,startwith34or37,15digitslong:(($type=='a')&&(!(($d2==34)||($d2==37))||($len!=15)))||//IfDiscover:startwith6011and16digitslong(($type=='d')&&((substr($num,0,4)!=6011)||($len!=16)))){//Invalidcard:returnfalse;}//Ifwearestillhere,thentimetomanipulateanddotheMod10//algorithm.Firstbreakthenumberintoanarrayofcharacters:$digits=str_split($num);//Nowreverseit:$digits=array_reverse($digits);//Doubleeveryotherdigit:foreach(range(1,count($digits)-1,2)as$x){//Doubleit$digits[$x]*=2;
//Ifthisisnowover10,goaheadandadditsdigits,easiersince//thefirstdigitwillalwaysbe1if($digits[$x]>9){$digits[$x]=($digits[$x]-10)+1;}}//Now,addallthisvaluestogethertogetthechecksum$checksum=array_sum($digits);//Ifthiswasdivisibleby10,thentrue,elseit'sinvalidreturn(($checksum%10)==0)?true:false;}//Checkvariouscreditcardnumbers:$nums=array('344234534664577'=>'a','3794234534664577'=>'a','4938748398324'=>'v','4123-1234-5342'=>'v','5184729384567434'=>'m','5723x2345x2345x6161'=>'m','6011601160116011'=>'d','6012392563242423'=>'d',);foreach($numsas$num=>$type){$st=standardize_credit($num);$valid=validate_credit($st,$type);$output=$valid?'Valid':'Invalid';echo"<p>{$st}-{$type}={$output}</p>\n";}?>
PHP具有非常出色的日期工具,極大地簡化了日期標準化和檢驗工作。特別是strtotime()函數(shù)能夠把絕大多數(shù)表示日期的字符串轉化為UNIX時標,如果轉化失敗,它會返回False。這個工具擁有非常強大的功能,幾乎不需要我們再做其他工作。在轉化為時標之后,我們就可以根據需要使用date()將它格式化為任何式樣,如程序清單11.6.1所示。程序清單11.6.1使用strtotime()和date()實現(xiàn)日期標準化和檢驗<?php//Runagainstvariousdates$dates=array('Dec31973','12/3/73','1973-12-3','1/0/2005','3/32/2004','0/1/0','12/3/973','2/31/2006','13/30/05');//Initialisethetimezonesettings,andloopoverallthevalues:date_default_timezone_set('America/New_York');foreach($datesas$d){//Convertit&validateatthesametime:$output=strtotime($d);//Preparethedisplay,either'BADDATE'oraformattedversion$disp=($output===false)?'BADDATE':date('m/d/Y',$output);echo"<p>{$d}={$disp}</p>\n";}</?>需要提醒的是,strtotime()函數(shù)的某些功能在一開始可能會讓人感到迷惑。例如它允許任何一個月的日期都可以到31日,但如果相應的月份不應該有31天,它會自動變化到有效的日期,因此11/31/2005會轉化為12/1/2005。它還允許第0天(實際上返回的日期是上一個月的最后一天),而0月表示十二月,0年表示2000年。11?7電子郵件賬戶
電子郵件賬戶遵循特定的格式,它必須由字符、數(shù)字或破折號開始,之后可以有任意數(shù)量的上述字符及句點,接著是“@”和域名。域名包含任意數(shù)量的“單詞”及分隔它們的句點,而這些“單詞”是由字符、數(shù)字和破折號組成的。最后一個后綴必須是2?6個字符長。(有些程序員只允許2或3個字符,這是不對的,因為沒有考慮到最新的頂級域名,如museum。)程序清單11.7.1所用的檢驗方法會允許足夠短但不是真正有效的頂級域名,比如.books,但與搜索冗長的有效域名列表相比,這種方法簡單多了。程序清單11.7.1電子郵件地址檢驗<?php//Afunctiontocheckvalidityofemailaccounts:functionvalidate_email($address){//Checkagainstamassiveregexforvalidity...returnpreg_match('/人[a-z0-9_-][a-z0-9._-]+@([a-z0-9][a-z0-9-]*\.)+[a-z]{2,6}$/i',$address);}//Runagainstvariousemailaccounts$email=array('author@','bob_123.3@','mrmrmr@bob.lawnmower','$bob$@','bob@gmail');//Loopoverthesevalues,determineiftheyarevalidemailsornow.foreach($emailas$e){//Validate:$output=validate_email($e);//Preparethedisplay,either'BAD'or'GOOD'$disp=($output==false)?'BAD':'GOOD';echo"<p>{$e}={$disp}</p>\n";}}}?>當然,這段代碼只是檢驗輸入的電子郵件地址是否屬于有效范圍,而且只允許使用最常見的形式?,F(xiàn)實中存在著一些其他形式,需要對代碼進行少許修改才能適應。特別是主機名應該可以用包圍在方括號里的IP地址表示;用戶名也應該可以用雙引號包圍的字符串表示,其中允許包含空格。但在當今的互聯(lián)網上,這種情況是很少見的。進一步實際檢查電子郵件地址是否真正存在的工作將在第16章16.2小節(jié)介紹。11?8URL如果表單里請求用戶輸入其主站地址,那么就需要對這個URL進行檢驗來判斷它是否像個有效地址。對URL的檢驗有兩個層次。一是使用parse_url()函數(shù)嘗試解析URL,對其中的組成部分進行基本的完整性檢查。二是嘗試連接相應的Web服務器,查看這個URL是否真正存在。但是一定要注意這種方法存在缺陷,因為服務器可能在當時恰好關機了。程序清單11.8.1展示了URL的標準化與檢驗例程。程序清單11.8.1URL標準化和檢驗函數(shù)庫<?php//AfunctiontodoasanitycheckonaURISinceweareassuming//thatthisiscomingfromuserinput,wewillrequireitbeafull//URL,andnotarelativeonefunctionvalidate_url($url){//Useparse_urltobreaktheURLintopartsforus:$up=parse_url($url);//Ifscheme,host,orpathdon'texist,orcompletefailure:INVALIDif(!$up||!$up['scheme']||!$up['host']||!$up['path']){returnfalse;//Iftheschemeisanythingbesideshttp(S)orftp:Failif(!(($up['scheme']=='http')||($up['scheme']=='https')||($up['scheme']=='ftp'
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 建筑自動化防盜門安裝合同
- 培訓機構講師聘用合同范文
- 精英社區(qū)房屋轉讓合同樣式
- 2024幼兒園新生入園安全協(xié)議書及家長育兒指導與責任合同2篇
- 智能化小區(qū)地源熱泵安裝協(xié)議
- 醫(yī)療康養(yǎng)區(qū)二手房按揭合同范本
- 商務旅行民宿管理指南
- 鋼結構工程安裝施工合同工裝
- 陶瓷行業(yè)保障:汽車租賃合同協(xié)議
- 旅游業(yè)者離婚協(xié)議書模板
- 安徽省合肥市蜀山區(qū)2024-2025學年七年級上學期地理期末模擬練習(含答案)
- 新建設項目施工人員安全教育培訓課件
- 江蘇省揚州市2024-2025學年高中學業(yè)水平合格性模擬考試英語試題(含答案)
- 品質總監(jiān)轉正述職報告
- 2024年游艇俱樂部會員專屬活動策劃與執(zhí)行合同3篇
- 《項目管理培訓課程》課件
- 2024年企業(yè)團購:銷售合作協(xié)議3篇
- 2024-2025學年八年級語文上學期期末真題復習 專題06 文言文閱讀
- 2024秋國開《管理學基礎》形考任務(1234)試題及答案
- 叉車安全管理
- 制藥課程設計三廢處理
評論
0/150
提交評論