下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1PHP與初學(xué)者相比,高級PHP以理解的特性中獲益。舉例來說,盡管我們已經(jīng)知道如何使用數(shù)組,但是對數(shù)組未必精通:如創(chuàng)建數(shù)據(jù)、對其進(jìn)行排序等操作?;蛟S我們已經(jīng)知道如何編寫自定義函數(shù),但是不一定知道如何使用遞歸以及靜態(tài)變量。本章將討論這類問題以及其他一些非基礎(chǔ)的概念,比如原的語法以及 數(shù)由于數(shù)組的強(qiáng)大和靈活性,使其在PHP編程中得到了廣泛的應(yīng)用。對于高級應(yīng)用來說,數(shù)組經(jīng)常用來解決其他第一個例子將展示如何對一個數(shù)組進(jìn)行排序。這是一lis, 在PHP
圖1-1數(shù)組的應(yīng)用方式之sort()、ksort等相關(guān)函數(shù)。使用它們,可以對一維數(shù)組進(jìn)行關(guān)鍵字排序、按值排序、逆排序$a=array('key1'=>23,'key2'=>'this'),array('key1'=>894,'key2=>'that')PHP5.4中新增了數(shù)組的縮寫語法,這為創(chuàng)建數(shù)組提供了一種簡便的方式。使用數(shù)組的縮寫語法的方式也很簡單,將調(diào)用array()函數(shù)替換為方括號即可。舉例://Old$a=array();//$b=array('this'=>//New$a=[];//$b=['this'=>這是一個簡單的二維數(shù)組(數(shù)組的元素本身也是數(shù)組key1(數(shù)值排序)或key2(字符順序排序。為了對數(shù)組進(jìn)行排序,我們需要定義自己的排序函數(shù),然后告訴PHP在調(diào)用usort()、uasort()或者uksort()的時候使用我們的自定義排序函數(shù)。它必須接收兩個參數(shù),并且返回一個值表示哪個參數(shù)應(yīng)該排面。負(fù)數(shù)或者false意味著第一個參數(shù)應(yīng)該排在第二個參數(shù)前面。正數(shù)或者true則表示第二個參數(shù)應(yīng)該排面。如果值為0,則舉例來說 為了對前面提到的數(shù)組根據(jù)第一個關(guān)鍵字進(jìn)行排序,我們的自定義排序函數(shù)可以寫成這樣:functionasc_number_sort($x,returntrue;{return}elsereturn}}PHP中這樣使用它(1-2usort($a,PHP會把內(nèi)層數(shù)組不斷地發(fā)送給這個函數(shù),從而將其排序。如果我們想要了解細(xì)節(jié),那么可以輸出函數(shù)里被比較的數(shù)值,我們可以看到自定義排序函數(shù)是如何被調(diào)用的,如圖1-3所示。Usort()函數(shù)根據(jù)數(shù)值進(jìn)行排序,但是它不保存關(guān)鍵字(對于外層數(shù)組來說。當(dāng)我們使用uasort()函數(shù)時,關(guān)鍵字就會被保存。當(dāng)我們使用uksort()函數(shù)時,排序?qū)⒒?圖1-2數(shù)組根據(jù)數(shù)值排序 圖1-3輸出$x['key1']和$y['key1']的如果想對前例數(shù)組的第二個關(guān)鍵字進(jìn)行排序,就需要對字符串進(jìn)行比較。相關(guān)代碼如圖1-4functionstring_sort($x,{return?}usort($a,1-4key2按字母進(jìn)行排()在文本編輯器或集成開發(fā)環(huán)境(IDE)中創(chuàng)建一個PHP,命名為sort.php。該文件以一段HTML代碼開始,如1.1所示。<!doctype<html??<link?<?php#Script1.1-1.1這個定義了一個二維數(shù)組 <!doctype<html<metacharset="utf-<title>SortingMultidimensional<linkrel="stylesheet"<?php#Script1.1-sort.php/*Thispagecreatesamultidimensional*ofnamesand*Thearrayisthensorted*oncebynameandonceby//Createthe//Array//studentID=>array('name'=>'Name','grade'=>$students= 256=>array('name'=>'Jon','grade'=> 2=>array('name'=>'Vance','grade'=>9=>array('name'=>'Stephen','grade'=>364=>array('name'=>'Steve','grade'=>68=>array('name'=>'Rob','grade'=> //Namesortingreturnstrcasecmp($x['name'],31//Gradesorting//SortinDESCENDINGfunctiongrade_sort($x,$y)return($x['grade']<37//Printthearrayasuasort($students,echo'<h2>ArraySortedByName</h2><pre>'.print_r($students,1).'</pre>';//Sortbyuasort($students,echo'<h2>ArraySortedByGrade</h2><pre>'.print_r($students,1).'</pre>'; 可能你注意到了我在本所有的示例中使用了HTML5,即便這不會對PHP代碼產(chǎn)生任何影響。我還使用了一個來自HTML5Boilerplate(/)的簡單 $students=256=>array('name'=>?'grade'=>?'grade'=>?'grade'=>364=>array('name'=>?'grade'=>68=>array('name'=>?'grade'=>外層數(shù)組$students有5IDfunctionname_sort($x,{return?}trcaecmp()函數(shù)會返回一個數(shù)值—負(fù)數(shù)、0或者正數(shù),表示這兩個字符的相似程度?;匾粋€數(shù),表示二個符串。果返回0則表示兩個字符串完全等。unctiongrade_srt($x,{return($x['grade]?$y['grade}這個例子類似前面介紹的示例程序,不過更加精簡。一個明顯的區(qū)別是這個例子會進(jìn)行降序排序,將最好的成績排在最前面。這很容易實現(xiàn):把比較操作符從大于修改為小于就可true值,這也就意味著第二個參數(shù)應(yīng)該排在順序列表的前面。echo'<h2>ArrayAsIs</h2><pre>'使用print_r()函數(shù)來快速打印出數(shù)組的內(nèi)容。為了提高可讀性,打印的內(nèi)容將使用<pre>進(jìn)行包裹uasort($students,?($students,1).因為這里使用了uasort()函數(shù),所以關(guān)鍵字,也就是學(xué)生的ID,不會丟失,如圖1-5所示。如果只是使用了函數(shù)usort(),排序結(jié)果將會把這些關(guān)鍵字丟掉,如圖1-6所示。uasort($students,?Grade</h2><pre>'.?($students,1).保存文件為sort.php,將其放置于你的 圖1-5數(shù)組按照排 圖1-6參看1.1,如果 圖1-7數(shù)組根據(jù)成績降序排使用函數(shù)uasort將會導(dǎo)致關(guān)如果我們回想一下,大多數(shù)數(shù)據(jù)庫查詢都返回一個數(shù)組,如圖1-8所示。如果查詢結(jié)果只是作為一個整體發(fā)送,那么這種數(shù)組的結(jié)構(gòu)并不會讓代碼變得復(fù)雜。但如果想對 圖1-8從數(shù)據(jù)庫中選擇包含多個字段的多條記錄就產(chǎn)生了一個數(shù)eb務(wù)列表系統(tǒng)。如果任務(wù)列表是一維的,就不會有什么難度。但是如果列表是可以嵌套的,其中每一項任務(wù)又可以有很多個步驟,那么就會得到一種樹形的結(jié)構(gòu),其中每個分支都可以具1-9所示。SubsubtaskSubsubtaskSubtaskAnotherMustDoSubtaskSubtaskCREATETABLEtaskstask_idINTUNSIGNEDNOT?parent_idINTUNSIGNEDNOT?DEFAULTdate_addedTIMESTAMPNOTNULL,pletedTIMESTAMP,PRIMARYKEY(task_id),INDEXaddedINDEXcompleted
1-9嵌套的工作列表在結(jié)構(gòu)上類似task10MustDotask10MustDo20Another30MyNew42Subtask52Subtask62Subtask Subsubtask數(shù)據(jù)類型VARCHAR(100);如果需要更長的描述,可以把它定義為文本類型(texttype)。最后項都有一個parent_id一個子任務(wù),那么它的parent_id的值就是對應(yīng)的列表項的值,如圖1-10所示。如果這個列表項不是子任務(wù),它的
1-10這個表格展示的數(shù)據(jù)和1-81-圖的中一樣。在字段task_id和parent_id之間有偽外鍵和主鍵的對應(yīng)關(guān)系0。這是為了實現(xiàn)靈活的嵌套結(jié)構(gòu)的簡單設(shè)置,但是在PHP中的處理會花費(fèi)一些功夫。表。接下來的內(nèi)容介紹如何在這個表中增加新任務(wù)的PHP。在本章接下來的幾個在你的文本編輯器或者集成開發(fā)環(huán)境中新建一段PHP,命名為php,以下面的HTML代碼開始,如1.2所示<!doctype<html<title>Adda<link?<?php#Script1.2-$dbc=本例中使用的是MySQL,而且在代碼中使用了改進(jìn)的MySQL函數(shù)。你需要改變對應(yīng)的.2 使用以下向數(shù)據(jù)庫中添加任務(wù)。利用下拉菜單可以將任務(wù)歸于其他任務(wù)執(zhí)行<!doctype<html<metacharset="utf-<title>Adda<linkrel="stylesheet"<?php#Script1.2-add_task.php*Thepagebothdisplaysandhandlesthe//Connecttothe$dbc=mysqli_connect('localhost','username','password','test'); //Sanctifytheinput...//Theparent_idmustbean$parent_id=}else$parent_id= //Escapethe$task=mysqli_real_escape_string($dbc,strip_tags($_POST['task']));$q="INSERTINTOtasks(parent_id,task)VALUES($parent_id,$r=mysqli_query($dbc,$q);//Reportontheecho'<p>Thetaskhasbeen}elseecho'<p>Thetaskcouldnotbe //Displaytheecho'<formaction="add_task.php"<legend>Adda<p>Task:<inputname="task"type="text"size="60"maxlength="100"<p>ParentTask:<selectname="parent_id"><optionvalue="0">None</option>';//Retrieveall pleted$q='SELECTtask_id,parent_id,taskFROMtasks pleted="0000-00-00?ORDERBYdate_added$r=mysqli_query($dbc,//Alsostorethetasksinanarrayforuse$tasks=//Fetchthewhile(list($task_id,$parent_id,$task)=mysqli_fetch_array($r,{ //Addtothe$tasks[]=array('task_id'=>$task_id,'parent_id'=>$parent_id,'task'=>$task); //Completetheechofunctionparent_sort($x,$y)return($x['parent_id']> usort($tasks,//Displayalltheecho'<h2>CurrentTo-Doforeach($tasksas$task)echo echo該表單有一個主文本框和一個下拉菜單,如圖1-11所示。為了檢查表單的提交情況,這個條件語句查看這個請求方法是命名為確保parent_id的值是個整數(shù):?FILTER_VALIDATE_INT,$parent_id?}else$parent_id=
1-11HTML表}這里parent_id的值是另一個任務(wù)的task_id值。其數(shù)據(jù)來源于一個下拉菜單,這意味著它來確保這里的值是比1大的整數(shù)。如果因為某種原因,不是這種情況,那么其值將為0。這里提到的過濾擴(kuò)展在PHP5.2PHP內(nèi)核。如果對其不甚了解,可以參考PHP手冊。$task=?myqli_real_escape_tring()函數(shù)會處理提交的描述任務(wù)的字符串,使其對于查詢操作來說是安全的。為了防止跨站注入XS),trip_tags()函數(shù)也同時用于檢查描述任務(wù)的字符串。$q="INSERTINTO?(parent_id,task)if(mysqli_affected_rows($dbc)?1)?}elseecho'<p>Thetaskcouldnot?}}//Endofsubmissionecho'<form?<legend>Adda<p>Task:<input?type="text"??一個有效值為0,表示不隸屬于其他任何任務(wù)的任務(wù)。?taskFROMtasksWHERE?completed="0000-00-00?ORDERBYdate_added這個查詢操作返回每個未完成任務(wù)的三個信息(一旦一個任務(wù)已經(jīng)完成,它的date_completed字段將會被賦予一個非零值。這里我們只選擇未完成的任務(wù),因為向一個已經(jīng)完這里的task_id和任務(wù)本身將用在下拉菜單中,parent_id將稍后用于嵌套任務(wù)。$tasks=圖1-12所示。這個數(shù)組將保存第二個列表中被使用的任務(wù)。1-12這個頁面有兩個地方包含了任務(wù)列while(list($task_id,?$task)=echo"<option??$task_id,'parent_id'}這個while1-131-13PHP代碼生成的下拉菜單的HTMLecho?value="AddThisparent_idfunctionparent_sort($x,{return($x['parent_id']?$y[}usort($tasks,這里,parent_id的作用在于區(qū)分務(wù)和子任務(wù),所以PHP foreach($tasksas$task)echo?}echo這個循環(huán)會基于parent_id1-1所示列表的第一步。但是從圖1-12中可以看出,列表還沒有達(dá)到其應(yīng)有的結(jié)構(gòu),把文件保存為add_task.php并放到我們的 如圖1-14所示
1-14針對一個存在的任務(wù)添加PHP5“悄悄地”為函數(shù)的參數(shù)增加了類型約束(typehintin)定函數(shù)中的參數(shù)是什么類型的變量。舉例來說,下面的代碼表示這個函數(shù)有一個唯一的數(shù)組類型的參數(shù)類型限制,但是標(biāo)量類型如字符串和整型除外。正如你將在本書后面章節(jié)中看到的那樣,類6章中詳細(xì)講解。高級函數(shù)定PHP程經(jīng)驗的程序員,也應(yīng)該已經(jīng)在代碼中創(chuàng)建了很多自定義函數(shù)了。但是在高級編程領(lǐng)域,自4遞歸靜態(tài)?以方式接收?函遞歸(recursion)就是函數(shù)自functionsomefunction()//Somecode.//Possibleother} functionlist_dir($start)$contents=scandir($start);foreach($contentsas$item){if(is_dir("$start/$item")//Use$item.}else//Use}//Endofif-}//Endof}//Endoffunction.函數(shù)的執(zhí)行操作(最后一行)調(diào)用函數(shù)list_dir('.'),設(shè)定當(dāng)前 作為起點。在該函數(shù)中,scandir()函數(shù)得 的內(nèi)容,然后利用foreach循環(huán)遍歷每一個條目。如果該條目,函數(shù)將被再次調(diào)用,但是使用新的作為起點參數(shù)。遞歸函數(shù)將在每個子被在使用遞歸的時候,需要注意兩件事情。第一個事情就是,像使用循環(huán)一樣,我們需要確保函數(shù)中有一個退出(ou)語句:到達(dá)某個條件,將使函數(shù)終止調(diào)用它自己。在上面的例子中,函數(shù)將在遍歷完子第二件需要注意的事情是,從服務(wù)器資源的角度來說,遞歸函數(shù)的成本是比較高的。需要銘記在心的是,每一次函數(shù)調(diào)用都是需要消耗內(nèi)存和處理器的,并且第一次調(diào)用必須等到其他所有調(diào)用都結(jié)束時才會結(jié)束。遞歸的層次如果比較深,比如100次遞歸,就有可能使服務(wù)器死機(jī)。簡單地說,有時遞歸是唯一的解決方案,但是通常情況下應(yīng)使用循環(huán)更加高效。在本章開頭創(chuàng)建的任務(wù)列表中,獲取和展示所有的任務(wù)項目不是很難(參見圖1-12)。然而,在add_task.php(1.2)中定義的方法并不能完全適合在圖1-1中的嵌套任務(wù)結(jié)構(gòu)。在文本編輯器或者集成開發(fā)環(huán)境中新建一個PHP,并命名為view_tasks.php,并且以下面的HTML代碼開始(詳細(xì)代碼見1.3)。<!doctype<html<h2>CurrentTo-Do<?php#Script13-function{global$tasks;echo'<ol>';這個函數(shù)接收一個數(shù)組作為參數(shù),在參數(shù)內(nèi)部需要能夠數(shù)組$tasks(主數(shù)組)—我1.3 <!doctype<html<metacharset="utf-<title>View<linkrel="stylesheet"<?php#Script1.3-view_tasks.php/*Thispageshowsallexisting*Arecursivefunctionisusedtoshow*tasksasnestedlists,as//Functionfordisplayinga//Receivesoneargument:anfunction{//Needthemain$tasksglobalecho'<ol>';//Startanorderedlist.//Loopthrougheachforeach($parentas$task_id=>{//Displaytheecho//Checkfor//Callthisfunction echo'</li>';//Completethelistitem. echo'</ol>';//Closetheorderedlist. }//Endofmake_list()function.//Connecttothe$dbc=mysqli_connect('localhost','username','password','test');//Retrieveall pleted$q='SELECTtask_id,parent_id,taskFROMtasks pleted="0000-00-00?ORDERBYparent_id,date_added$r=mysqli_query($dbc,//Initializethestorage$tasks=//Loopthroughthewhile(list($task_id,$parent_id,$task)=mysqli_fetch_array($r,{//Addtothe //For//Sendthefirstarray//tothemake_list() foreach($parentas$task_id?$todo)echoforeach循環(huán)將遍歷整個數(shù)組,并在<li>中顯示每個元素if{}這是這個最重要的部分。從數(shù)據(jù)庫獲取的任務(wù)列表可能是如圖1-15所示的那樣的一個數(shù)組。對于主數(shù)組來說,關(guān)鍵字是parent_id,而元素是位于這個parent_id之下的任務(wù)集合。因此,在打印出了初始的<li>和任
圖1-15這段PHP (或者,這個任務(wù)是不是一個父任務(wù)元素?)。換句話說,在$tasks里是否有元素的關(guān)鍵字的值是這個任務(wù)的ID?如果有,當(dāng)前任務(wù)就有子任務(wù),因此這個函數(shù)需要被再次調(diào)用,以數(shù)組的這一部分(關(guān)鍵字的值是這個task_id,其值是子任務(wù)數(shù)組的元素)作為參數(shù)。foreachecho}//EndofFOREACHloop.echo'</ol>';}//Endofmake_list()$dbc=中,然后調(diào)用一次make_list()函數(shù)。?taskFROMtasksWHERE?completed="0000-00-00?ORDERBYparent_id,?這個查詢獲取每個任務(wù)項的3個信息:ID、parent_id以及任務(wù)的內(nèi)容。其中的條件表示只選擇未完成的任務(wù)。得到的結(jié)果以parent_id進(jìn)行排序,所以頂級任務(wù)(parent_id為0的任務(wù))會首先返回。次要排序參數(shù)是date_added,可以讓任務(wù)按照其被添加的次序返回(假定$tasks=while(list($task_id,?$task)=$tasks[$parent_id][$task_id]?}這里的$tasks數(shù)組將保存二維數(shù)組中的每一項任務(wù),如圖1-15所示。正如在第4步中介紹的那樣,數(shù)組最外層的關(guān)鍵字是來自數(shù)據(jù)表的parent_id的值,而最外層數(shù)據(jù)的元素是具有相應(yīng)的parent_id值的任務(wù)。?在處理數(shù)組時,知道和理解相應(yīng)的結(jié)構(gòu)是至關(guān)重要的。如果取消這一行的注釋去1-15make_lit雖然變量$tasks是個數(shù)組,但是make_list()函數(shù)只需要被調(diào)用一次,并把第一個數(shù)組元素傳遞給它。這個元素的值是一個由parent_id為0的任務(wù)組成的數(shù)組。在這個函數(shù)中,保存文件為view_tasks.php并放到 中,然后在瀏覽器中測試,如圖1-
使用add_task.php來添加的子任務(wù),重新在瀏覽器中測試該,如圖1-圖1-16任務(wù)頁面,以嵌套形式顯示任務(wù)列 圖1- make_list()$tasks在使用遞歸函數(shù)時 事實上,在使用任何可能會被多次調(diào)用的函數(shù)時,我們都應(yīng)考慮使用靜態(tài)變量。靜態(tài)變量讓函數(shù)在多次被調(diào)用時記住變量的值,而這些變量并不是全局變量。舉例來說,make_lit()函數(shù)可以重寫一,完整的任務(wù)列表作為其第二個參數(shù)并且為可選參數(shù),賦給一個靜態(tài)本地變量static$tasks=}make_list($tasks[0],1-17中,顯示被比較的數(shù)值并不難,但是統(tǒng)計遞歸的次數(shù)就需要使用靜態(tài)變量了。為了演示這種用法,sort.php將按照下面的步驟進(jìn)行修改。像下面這樣來修改name_sort()函數(shù)(詳見1.4):functionname_sort($x,{static$count=?return?}1.4 <!doctype<html<metacharset="utf-<title>SortingMultidimensional<linkrel="stylesheet"<?php#Script1.4-sort2.php/*Thispagecreatesamultidimensional*ofnamesand*Thearrayisthensorted*oncebynameandonceby*Astaticvariablehasbeenaddedto*functionstoseehowmanytimestheyare//Createthe//Array//studentID=>array('name'=>'Name','grade'=>$students= 256=>array('name'=>'Jon','grade'=> 2=>array('name'=>'Vance','grade'=>9=>array('name'=>'Stephen','grade'=>364=>array('name'=>'Steve','grade'=>68=>array('name'=>'Rob','grade'=> //Namesortingfunctionname_sort($x,$y)//Showiterationsusingastaticstatic$count=echo"<p>Iteration$count:{$x['name']}vs.returnstrcasecmp($x['name'], //Gradesorting//SortinDESCENDING//Showiterationsusingastaticstatic$count=echo"<p>Iteration$count:{$x['grade']}vs.return($x['grade']< uasort($students,echo'<h2>ArraySortedByName</h2><pre>'.print_r($students,1).'</pre>';//Sortbyuasort($students,echo'<h2>ArraySortedByGrade</h2><pre>'.print_r($students,1).'</pre>'; 這個函數(shù)里添加了3行代碼,第一行了一個靜態(tài)變量,名稱為$count。它的初始值為1,但是這個賦值操作只在函數(shù)第一次被調(diào)用時執(zhí)行(因為它是一個靜態(tài)變量。然后下一的值。最后,變量$count的值被增加1。functiongrade_sort($x,{static$count=??}這里為grade_sort()函數(shù)添加的3行代碼和添加在name_sort()函數(shù)中的是一樣的,只是其中用于比較的關(guān)鍵字是grade而不是name。保存文件,并命名為sort2.php,放在Web 圖1-18所示。(同時我也移除了打印數(shù)組原始結(jié)構(gòu)的那行代碼)為$students數(shù)組增加一些額外的元素,然后再次運(yùn)行,結(jié)果如圖1-19所示圖1-18對原始的5元素數(shù)組按照進(jìn) 圖1-19向主數(shù)組增加3個元后,根排序需要調(diào)用6次排序函 名字的排序需要20次遞歸調(diào)1.2.3函本部分要討論最后一個高級話題:函數(shù)(anonymousfunction,亦稱lambda)的使用。簡單地說,一個函數(shù)就是一個沒有名字的函數(shù)。創(chuàng)建函數(shù)的特性是在PHP5.354創(chuàng)建一個函數(shù)的方式和我們創(chuàng)建其他函數(shù)沒有什么不同,只是,它沒有一個名字。然而,為了方便之后這個函數(shù)例如該,這個函數(shù)的定義需要賦值給個變量。 o={echo 看上去這種做法有些不太容易理解,但是前提其實很簡單:就像賦值給一個字符串或者整數(shù)類型的變量一樣,我們只是給一個函數(shù)定義賦值。由于這個原因,在賦值語句結(jié)束時需粗略來說為了調(diào)用函數(shù)(當(dāng)然在其被定義好了之圖1-20所示。圖1-20通過變量調(diào) 這種使用函數(shù)的特殊方式有其優(yōu)勢所在,但是也有一種更加明顯和簡單的方式來使用函數(shù),我們需要討論一下。PHP中一些函數(shù)可以使用另一個函數(shù)作為其參數(shù),舉例來說,array_map()函數(shù)接收一個函數(shù)作為其第一個參數(shù),第二個參數(shù)是個數(shù)組,數(shù)組內(nèi)的每個functionformat_names($value)//Dowhateverwith}array_map('format_names', 函數(shù),你可以在函數(shù)參數(shù)內(nèi)定義一個函數(shù)array_map(function($value)//Dowhateverwith},?由于函數(shù)是被直接使用的,因 只需要函數(shù)的定義就可以了 的時候。在接下來的步驟中,最后更新一次sort.php的代碼來使 函數(shù)。注意PHP5.3刪除當(dāng)前對函數(shù)name_sort()和grade_sort()的定義代碼(1.5)。修改第一次對uasort()函數(shù)的調(diào)用,這里使用函數(shù)的方式uasort($students,function($x,$y)return?修改第二次對uasort()函數(shù)的調(diào)用,這里使用函數(shù)的方式uasort($students?保存文件為sort3.php,放到Web 121PHP5.3之前的版本,我們也可以使用create_function()函數(shù)來創(chuàng)建和函數(shù)類似的函數(shù)。
1-21最終結(jié)果沒有因為使用函數(shù)可以用做閉包,一個公認(rèn)的高級概念。閉包在PHPJavaScript1.5 <!doctype<html<metacharset="utf-<title>SortingMultidimensional<linkrel="stylesheet"<?php#Script1.5-sort3.php/*Thispagecreatesamultidimensional*ofnamesand*Thearrayisthensorted*oncebynameandonceby*Thisversionusesanonymous//Createthe//Array//studentID=>array('name'=>'Name','grade'=>$students= 256=>array('name'=>'Jon','grade'=> 2=>array('name'=>'Vance','grade'=>9=>array('name'=>'Stephen','grade'=>364=>array('name'=>'Steve','grade'=>68=>array('name'=>'Rob','grade'=> uasort($students,function($x,$y)returnstrcasecmp($x['name'],32 echo'<h2>ArraySortedByName</h2><pre>'.print_r($students,1).'</pre>';//Sortbyuasort($students,function($x,$y)return($x['grade']<38 echo'<h2>ArraySortedByGrade</h2><pre>'.print_r($students,1).'</pre>'; 變量本身。也就是說,函數(shù)使用的其實是變量的一個副本。這種行為的結(jié)果就是在該函數(shù)內(nèi)functionincrement($var)}$num=2;echo$num;//Still取代這種默認(rèn)行為的一個方法是,將這個函數(shù)的參數(shù)傳遞方式設(shè)置為按照傳遞,而的值,而不需要使用全局變量。第二個好處是關(guān)于性能方面的。在需要傳遞的數(shù)據(jù)比較大的場景按傳意著PHP不需要去構(gòu)建一份數(shù)的副本。對于字符串或數(shù)字來說,PHP不需要functionincrement(&$var)}$num=2;echo$num;//或 functionincrement($var)}$num=2;echo$num;//3原型文檔語原型文檔(heredo)是一種封裝字符串的替代方式,它不像標(biāo)準(zhǔn)的單引號或者雙引號那樣使用頻繁,但是其具有相同的功能。使用原型文檔就像是把花生和黃油抹在香蕉上一樣:原型文檔的工作方式和雙引號一樣,它包裹的內(nèi)容將被打印出來,但是它還允許我們自己定義分界符。在要打印出大量的TL代碼包自身的雙引)的時候,原型文原型文檔以<<<開始,后面緊跟著分界符。分界符通常需要是全部大寫的單詞,它只能在字符串的末尾使用相同的分界符,但是這次沒有符號<<<。結(jié)束分界符必須位于單獨(dú)1-22$var=echo<<<EOTSomevar$varThisvar$that$string=<<<EODstringwith$var\necho圖1-22從結(jié)果中可以看出,使用原型文檔語法的結(jié)果和使引號的完全一使用ED和ET作為分界符是比較常見的方式(它們一般不會出現(xiàn)在字符串中,但是這并不是必須的。原型文檔的語法是個不錯的選擇,但是,說得更透徹些,它又是十分特殊的。如果語法不是百分之百準(zhǔn)確無誤,甚至只為了展示原型文檔的使用,我們來重寫文件view_tasks.php,讓用戶可以對任務(wù)進(jìn)行標(biāo)記,如圖1-23所示。在文本編輯器或者集成開發(fā)環(huán)境中打開文件view_tasks.php(1.3)。make_list(函數(shù)中,把打印任務(wù)的相關(guān)語句修改為(如1.6所示):
1-23查看任務(wù)列表的頁面現(xiàn)在多了復(fù)選框,echo?1.6 最初的view_tasks.php代碼(1.3)修改為一個表單,讓用戶可以對任務(wù)進(jìn)行標(biāo)記,這里使用原型文檔來創(chuàng)建一些HTML標(biāo)記<!doctype<html<metacharset="utf-<title>View<linkrel="stylesheet"<?php#Script1.6-view_tasks2.php/*Thispageshowsallexisting*Arecursivefunctionisusedtoshow*tasksasnestedlists,as*Taskscannowbemarkedas//Functionfordisplayinga//Receivesoneargument:anfunctionmake_list($parent)globalecho'<ol>';//Startanorderedforeach($parentas$task_id=>{//Startwithaecho<li><inputtype="checkbox"name="tasks[$task_id]"value="done">//Checkfor echo'</li>';//Completethelist}//EndofFOREACHecho'</ol>';//Closetheordered}//Endofmake_list()function.//Connecttothe$dbc=mysqli_connect('localhost','username','password','test');if(($_SERVER['REQUEST_METHOD']==&&&&&&!empty($_POST['tasks']))//Definethe$q='UPDATEtaskspleted=NOW()WHEREtask_idIN//Addeachtaskforeach($_POST['tasks']as$task_id=>$v) $q.=$task_id.', //Completethequeryand$q=substr($q,0,-2).$r=mysqli_query($dbc,//Reportontheif(mysqli_affected_rows($dbc)==count($_POST['tasks']))echo'<p>Thetask(s)havebeenmarkedas}elseecho'<p>Notalltaskscouldbemarkedas 67}//Endofsubmission//Retrieveall pleted$q='SELECTtask_id,parent_id,taskFROMtasks pleted="0000-00-00?ORDERBYparent_id,date_added$r=mysqli_query($dbc,$tasks=while(list($task_id,$parent_id,$task)=mysqli_fetch_array($r,MYSQLI_NUM))$tasks[$parent_id][$task_id]= //Makeaecho<p>Checktheboxnexttoataskandclick"Update"tomarkataskas?(it,andanysubtasks,willnolongerappearinthis<formaction="view_tasks2.php" //Completetheecho<inputname="submit"type="submit"value="Update" echo"<li><input??echo'<li><input?name="tasks['. ?&&isset($_POST['tasks'])只有在表單提交,$_POST[taks']有一個值,并且是一個非空的數(shù)組的時候,數(shù)據(jù)庫才會被更新使任務(wù)標(biāo)記為已完成。哪怕只有一個復(fù)選框被選中,$_POST[tasks']也會是一個數(shù)組。$q='UPDATEtasksSET?IN?$task_id=>$v)$q.=$task_id.',}$q=substr($q,0,-2).UPDATEtasks ?NOW()WHEREtask_idIN(X,Y, pleted字段設(shè)置為當(dāng)前日期和時間,這樣它就不會顯 pleted為空的任務(wù)條目。if?==count($_POST['tasks'])){?markedas}elseecho'<p>Notalltasks?bemarkedas}}//Endofsubmission在調(diào)用make_list()函數(shù)之前,先添加初始表單echo<p>Checktheboxnexttoa?andclick"Update"tomark?taskascompleted(it,and?subtasks,willnolonger?inthis<form由于make_list()函數(shù)的執(zhí)行效果,因此,只要父任務(wù)被標(biāo)記為已經(jīng)完成,子任務(wù)就不會在調(diào)用make_list()函數(shù)之后結(jié)束表單。echo把文件保存為view_tasks2.php,放在Web 目選中,標(biāo)記為已完成,如圖1-23所示,然后提交表單,如圖1-24所示。1-24更新之后的任務(wù)列知識拓展:nowdocPHP5.3nowdoc語法。nowdoc相對于原型文檔正如單引號對于雙引號一樣。也就是說,nowdoc提供了另外一種封裝字符串的方法,但是在nowdoc里的任何變量不會被從語法上來說,nowdoc遵循和原型文檔一樣的規(guī)則,唯一的區(qū)別在于,nowdoc中的分$var=stringwith$var澄清一下,$string$ver23printf()對于大多數(shù)PHP程序員來說,只需要使用print()和echo()這兩個函數(shù)來顯示文本和變量就足夠了。但是高級程序員則偶爾會使用更為復(fù)雜的printf()函數(shù),這個函數(shù)不僅能顯示文本,還可以設(shè)置輸出的格式。PHP手冊中對這個函數(shù)的定義如下:printf(stringformat[,?format是由直接文本變量和特殊格式參數(shù)組成的字符串。特殊格式參數(shù)由百分?符號說明符(+/–)可以強(qiáng)制?填充說明符表示用于右填充的字符(空格是默認(rèn)的,但是對于數(shù)字來說可能需要使用0)。?對齊說明符(默認(rèn)是右對齊的,使用減號(–)可以實現(xiàn)左對齊?一個數(shù)字,用于表示要占用的最小寬度。?精度說明符,表示浮點數(shù)應(yīng)該顯示小數(shù)點后的多少位(或者字符串里的多少個字符?類型說明符,見表1-11-1類型說明字含字含b二進(jìn)制f浮點c依照ASCII值的字o八進(jìn)制d帶符號十進(jìn)制整s字符e科學(xué)x十六進(jìn)制u無符號十進(jìn)制這些看起來似乎挺復(fù)雜的,但是也確實如此。我們可以從數(shù)字開始練習(xí)使用它,如圖1-25所示。printf('b:%b<br>c:%c?%d<br>f:%f,80,80,80,這是同一個數(shù)字的4種不同的表示方式。第一個格式把80顯示為二進(jìn)制數(shù)字,第二個格式顯示80對應(yīng)的ASCII字符(也就是大寫的P),第三個格式是個整型數(shù),第四個格式是在此基礎(chǔ)上,從中選擇兩種最常用的數(shù)字類型—d和f,然后再增加一些其他格式,如圖1-26所示。printf('%0.2f<br>%+d<br>%02f?8,8,圖1-25使用四種不同的類型說明符
1-26使用printf函數(shù)設(shè)置數(shù)字的首 數(shù)字8以浮點數(shù)表示,小數(shù)點后面有兩位小數(shù),不足的位數(shù)以0填充。然后,81235.456顯示為具有兩位小數(shù)的浮點數(shù)(結(jié)果中展示printf('Thecostof%d%sat$%0?sprintf()printf幾乎完全一樣,但是它不是顯示格式化的字符串,而
1-27混合打印出數(shù)字和字符在文本編輯器或者集成開發(fā)環(huán)境中打開add_task.php(1.2)。刪除對函數(shù)mysqli_real_escape_string()的調(diào)用(如1.7所示 定義INSERT語句的那行代碼做如下修改:$q=sprintf(INSERTINTO?(parent_id,task)??當(dāng)我們使用printf()SL命令和變量的方式來創(chuàng)建查詢語句了。盡管這里的例子中開始的代碼也不算太難看,但是對于更加復(fù)雜的查詢語來照寫能”會包很多$var[index']}這樣的東西,而且還很容易產(chǎn)生錯誤,不方便調(diào)試。使用sprintf()函數(shù)的方法可以有效地把查詢和要使用的數(shù)據(jù)分離,同時還能夠集成函數(shù)1.7對add_task.php頁面做些小的修改(如1.1所示),展示另一種簡潔的創(chuàng)建<!doctype<html<metacharset="utf-<title>Adda<linkrel="stylesheet"<?php#Script1.7-add_task2.php/*Thispageaddstaskstothetasks* $dbc=mysqli_connect('localhost','username','password','test');$parent_id=}else$parent_id= ?mysqli_real_escape_string($dbc,$r=mysqli_query($dbc,$q); echo'<p>Thetaskhasbeen }else echo'<p>Thetaskcouldnotbe //Displaytheecho'<formaction="add_task2.php"<legend>Adda<p>Task:<inputname="task"type="text"size="60"<p>ParentTask:<selectname="parent_id"><option$q='SELECTtask_id,parent_id,taskFROMtasks pleted="0000-00-00?ORDERBYdate_added$r=mysqli_query($dbc,$tasks=while(list($task_id,$parent_id,$task)=mysqli_fetch_array($r,MYSQLI_NUM))echo"<option$tasks[]=array('task_id'=>$task_id,'parent_id'=>$parent_id,'task'=> echo把表單的actionadd_task2.phpvie_task.php頁面)都能夠以更好的方式顯示任務(wù)列表,所以沒有必要在這里包含這些代碼。保存文件為add_task2.php,將其放在中,在瀏覽器中進(jìn)試,如圖1-28所示
1-28頁面的運(yùn)行情況和之前沒有區(qū)printf('Thetaxrateis?vprintf()與printf()從格式參數(shù)上來說,sscanf()和fscanf()函數(shù)分別等同于printf()和sprintf()scanf()函數(shù)用于輸入,而fscanf()用于從文件數(shù)據(jù)1.5回顧和啟示◆回顧和啟在本書的新版中,每一章將以一個“回顧和啟示”小節(jié)結(jié)束。在這些小節(jié)中,看到關(guān)于本章中討論過的知識材料相關(guān)的一些問題,還會提示讀者如何通過去擴(kuò)展自己的如果你對本章有任何問題,可以本書的支持 /forums/)使用什么函數(shù)去按值對一個數(shù)組進(jìn)行排序?如果排序中要保留關(guān)鍵字呢?如何按關(guān)鍵字對數(shù)組進(jìn)行排序?什么是函數(shù)?在PHP的哪個版本中引入了函數(shù)使用原型語法有哪些規(guī)則要遵循?和其他的替代方案相比,原型文檔的方式有什么優(yōu)勢?printf()和sprintf()1)sort.php,使用自定義函數(shù)的方式更優(yōu)雅地產(chǎn)生出結(jié)果。2)完成add_task.php文件,使其包含合適的錯誤處理。 使用本章中提供的建議之一,比如通過傳遞參數(shù),或者使用靜態(tài)變量,更()如果你好奇,可以在網(wǎng)上搜索一些PHP中使用函數(shù)的例子view_tasks.php,使其可以顯示已經(jīng)完成的和將要完成的任務(wù)列表,并以不在view_tasks.php文件中增加一個,在URL中傳遞一個參數(shù),用于標(biāo)示是所有任務(wù)都需要顯示出來,還是只顯示未完成的任務(wù)。根據(jù)傳入的參數(shù)值修改SQL查詢語句。修改文件尋找關(guān)于printf()和sprintf()函數(shù)的其他用法。提示:查看PHP手冊中關(guān)于這些函2WebPHP程序員的職業(yè)生涯通常是從專門完成一個特定功能的獨(dú)立的開始的。然后再逐漸使用越來越多的文件來建立Web應(yīng)用程序,最后可能會在自己的服務(wù)器上開發(fā)站點。如果幸運(yùn)的話,還可能會讓站點使用多臺不同的服務(wù)器。無論的項目有多大,在PHP程序員的日常工作中,學(xué)習(xí)開發(fā)Web應(yīng)用程序的新的和改進(jìn)的方式都是重要的組成部分。本章中,著重介紹初中級以上的Web應(yīng)用程序的開發(fā)。從解釋如何模塊化一個開始。然后學(xué)到一些關(guān)于ApacheWeb服務(wù)器的知識,包括使用它的mod_rewrite特性,用來生成對搜索引擎優(yōu)化(SEO)規(guī)則友好的地址(URL)。以筆者的經(jīng)驗來說,程序員的成長是從編寫完成比較單能的單個頁面程序開始的。一段時間之后,工作內(nèi)容將會變?yōu)殚_發(fā)含有多個頁面的,并且包括模板以及狀態(tài)管理。在不斷累一經(jīng)驗后,PHP程序員開始利用較少的頁面來完成和多面同樣多的工作。比如可以讓同一個既顯示表單同時又處理表單,不再使用兩個獨(dú)立的文件?;蛘?,恰相,高級PHP程序員開始編寫一系列具單能的程序,它們分別完成特定工作這最式正對eb站點行塊化設(shè)計的前提。這里舉例說明模塊化一個站點的方式。創(chuàng)建一個偽Web站點(也就是說,組成部分進(jìn)行分解、組織以及合成到一起。取代使用不同的單獨(dú)頁面的方式(比如contact.php、由于這個應(yīng)用程序沒有使用數(shù)據(jù)庫,因此這里我們沒有為其創(chuàng)建一個數(shù)據(jù)庫配置文件。如果需要使用數(shù)據(jù)庫,我們可以編寫創(chuàng)建數(shù)據(jù)庫連接的文件,命名為myql.inc.php或者potgresql.incphp、db.incphp這個文件應(yīng)該可以保存在 下,但是最好保存在 con?g.inc.phpDB,用于指定這個文件在服務(wù)器上的絕對路徑。 我們開發(fā)的每個Web程序都會由配置文件開始。配置文件可以有很多作用。最重要的定義??管理從根本上說,站點內(nèi)的每個頁面都有可能需要的信息就應(yīng)該保存在配置文件中。(這里順便提一下,對于不是大部分頁面都需要的函數(shù),把它放在單獨(dú)的文件里,從在21在21<?php#Script2.1-2.1 配置文件是關(guān)鍵的,它定義了范圍內(nèi)的常數(shù),并且指明了如何1<?php#Script2.1-234*Filename:5*Createdby:LarryE.6*Contact:,7*Lastmodified:June5,8**Configurationfiledoesthefollowing*-Hassitesettingsinone*-StoresURLsandURIsas*-Setshowerrorswillbe #*****SETTINGS*****// ed ='a //Determinewhetherwe'reworkingonalocal//oronthereal}else //DeterminelocationoffilesandtheURLofthe//Allowfordevelopmentondifferent{//Alwaysdebugwhenrunning$debug=TRUE;//Definethe }{ *Mostimportant*The$debugvariableisusedtoseterror if($p=='thismodule')$debug= *Todebugtheentiresite,do $debug= *beforethisnext //Assumedebuggingis $debug= #*****SETTINGS***** #**************************** #*****ERRORMANAGEMENT***** //Createtheerror functionmy_error_handler($e_number,$e_message,$e_file,$e_line,{ global$debug,$contact_; //Buildtheerror $message="Anerroroccurredinscript'$e_file'online$e_line:$e_message"; //Append$e_varstothe $message.=print_r($e_vars, if($debug){//Showtheerror. echo'<divclass="error">'.$message. }{ error_log($message,1,$contact_);//Send. //Onlyprintanerrormessageiftheerrorisn'tanoticeor if(($e_number!=E_NOTICE)&&($e_number<2048)) echo'<divclass="error">Asystemerroroccurred.Weapologizefor? 105}//Endofmy_error_handler()definition.//Usemyerror#*****ERRORMANAGEMENT*****#*****************************Filename:*Createdby:LarryE.*Contact: ?*Lastmodified:June5,**Configurationfildoes?following*-Hassitesettingsin?*-StoresURLsandURIs?*-Setshowerrorswill?由于配置文件是比較通用的文件,因此它應(yīng)該是程序里注釋最好的。 ? 對于實際運(yùn)行的站點來說,我比較傾向于用戶在發(fā)現(xiàn)錯誤時能夠通過電子郵件的方式通知到我,因此我了一個變量,為每個通用的交流信息保存一個“發(fā)送到”的電子郵件地址。這個地址可以是的郵箱,但是一旦開發(fā)的站點實際運(yùn)行了,這就應(yīng)該是站點管理員的電子郵箱地址。$host=$local=}else$local=}我通常都會在本地服務(wù)器開發(fā),然后把完整的代碼上傳到實際的服務(wù)器。這兩種環(huán)境具有各自特定的設(shè)置。在理想情況下,配置文件應(yīng)該可以根據(jù)所處的服務(wù)器環(huán)境自動為了測試站點是否運(yùn)行于本地環(huán)境,我們首先檢查一下變量的前?單詞local(在中用到?IP地址的開始,192.1或者127.0,兩種情況都說明條件是否滿足,$local變量將會被賦予一個布爾值(真或者假),以便在后面的中使用。if($local)$debug=?'/path/to/html/folder/');?'?}{?? ?}我經(jīng)常在自己的Web應(yīng)用程序中使用3個常量。其中,常量BASE_URI在服務(wù)器上的絕對路徑。這個常量可以在中包含一個文件的時候很方便地使用絕對路徑來文件。如果你正在使用indows中的XAMPP開發(fā)環(huán)境,這個值就有可能是這樣的:xampphtdocs\ch02。常量BASE_URL是主機(jī)名和 是。最后,常量DB是包含數(shù)據(jù)庫連接信息的文件的絕對路徑。出于安全方面的考慮,這個常量最好保存在Web 可以注意到每一個常量在不同的環(huán)境下有不同的設(shè)置:一種是在測試服務(wù)器,另一種是在正式的線上服務(wù)器。如果是在測試服務(wù)器上($localTRUE),我同時還會打開$debug=}我們還使用了變量$debug$debug的值會為TRUE $debug=function?($e_number,?$e_file,$e_line,{global P允許我們定義自己的錯誤處理函數(shù),來取代使用內(nèi)置的處理機(jī)制。關(guān)于這個過程或者語的信息可以考P手冊者我一本書《PndyLorWebte:ialuckartudebook(acpte,2012)。$message="Anerroroccurred$message.=print_r($e_vars,出于調(diào)試的目的,錯誤消息中應(yīng)該盡可能多地包含信息。首先,它應(yīng)該發(fā)生錯誤的文件名以及行號。然后加上每個已經(jīng)存在的變量的值。這可能會是大量的數(shù)據(jù),如圖2-1所2-1當(dāng)調(diào)試站點時錯誤消息的顯if($debug){//Showtheerror.echo<divclass="error">'.?$message 如圖2-1在開發(fā)一個站點的時候是非常有用的,但是對實際運(yùn)行的站點來說,可能算是一個巨大的安全。這段代碼將把這些信息顯示在一個DIV中,這個有個類名為error,通過SS的設(shè)計也就說,以創(chuàng)一個殊的DIV或者不用它。}else? if(($e_number!=E_NOTICE)?($e_number<2048)){?Asystemerror?Weapologizefortheinconvnince}}//Endof$debug對于線上運(yùn)行的站點來說,不應(yīng)該顯示錯誤的詳細(xì)信息除非出于調(diào)試的目的暫時啟動相應(yīng)頁面的調(diào)試模式,而是應(yīng)該通過郵件的方式發(fā)送錯誤消息到設(shè)置的郵箱。函數(shù)error_log()的第二個參數(shù)為1時就能完成這種操作。但是對于用戶來說,需要知道站點出現(xiàn)了問題,因此站點會顯示一個通用的錯誤提示消息,如圖2-2所示。如果錯誤是個通知級別的錯誤,或者嚴(yán)格性錯誤值為2048,不應(yīng)該有任何信息打印出來。因為這種錯誤一般不會影響頁面的操作。2-2在實際運(yùn)行的站點上,錯誤消息的處理方式更加謹(jǐn)慎(和安全}//Endof?definition.?保存文件為con?g.inc.php,并放置在你的Web 下(在一個叫做includes的子圖2-3顯示了這個 結(jié)構(gòu)。注意到這里我沒有使用一個PHP的關(guān)閉(closingPHPtag)。這在PHP內(nèi)是可以接受的并且對于這種會被其他包含的文件來說,圖2-3根 (images)、包含文件(includes)以及模塊(modules)等將被用到像你的代碼結(jié)構(gòu)或者文檔一樣,在開發(fā)大型的Web應(yīng)用程序的時候,另外一個比較重要拆分成同的面和 。主eb檔 ,我之為html,我們應(yīng)有一個子目錄至,乎有會么、一個保存類的 如使了對編的、一個函數(shù) 等。更進(jìn)一,為了安全起見我比較傾于你去使用一個個性化名字來命名些文件夾。對有用戶來說,任何時候都不知道文件和文檔的名字,總是一件好事情。如果你對站點的管理模塊使用的名字為admin,從安全的角度來說,這樣不會給你帶來任何好處。TL以使用Smarty(.net)或者其他的模板系統(tǒng),但是我還是比較喜歡只使用兩個簡單的文件:一個頁頭文件包含頁面特定的內(nèi)容之前的全部內(nèi)容,一個頁腳文件包含頁面對于這個模板,使用HTML5WebTemplates(wwwhtml5webtemplates.co.uk)設(shè)計的HTML為了給Web站點創(chuàng)建一個模板,要獨(dú)立于所有的PHP代碼設(shè)計一個像標(biāo)準(zhǔn)的HTML頁面一樣的布局。對于這里的例子來說,正如前面提到的,使用ColourBlue設(shè)計模板,如圖2-4所示。注意為了節(jié)省本書篇幅,本例中使用的CSS文件(用于控制布局的)沒有包含在本書里,讀者可以從本書的支持( <!DOCTYPE<div這里第一個文件將包括原始的HTML(從DOCTYPE到頭部標(biāo)記再到頁面主體的開始。它還包含形成瀏覽器頂部欄和右側(cè)邊欄的代碼,如圖2-4所示。書中在此將跳過大量的HTML代碼。完整的代碼請參見2.2或者直接從本書的支持站點。2-4本站將為所有的頁面使用的模<title><?phpecho?我們希望頁面的標(biāo)題(出現(xiàn)在Web24colour_blue)能夠在逐頁的基礎(chǔ)上產(chǎn)生變化。為此,里使用一個變量來表示標(biāo)題,它將通過PHP輸出。2.2 HTML模板的開始。它包含CSSPHP變//ThispagebeginstheHTMLheaderforthesite.//Checkfora$page_titleif(!isset($page_title))$page_title='DefaultPage?><!DOCTYPE8<title><?phpecho$page_title;<linkrel="stylesheet"type="text/css"href="style/style.css"title="style"<div<div<div<div<h2>Simple.Contemporary.Website<div <ul <li><a<li><a<li><a<li><a<li><a <div<div<h3>Latest<h4>NewWebsite<h5>January1st,<p>2010seestheredesignofourwebsite.Takealookaroundandletusknowwhat?think.<br/><ahref="#">Read<h3>Useful <li><ahref="#">link <li><ahref="#">link <formmethod="get"action="index.php" <inputtype="hidden"name="p"value="search"<inputclass="search"type="text"name="terms"value="Search..."<inputname="search"type="image"style="border:0;margin:00-9px?src="style/search.png"alt="Search"title="Search"<div<!--Endofheader.--HTMLPHP<?php#Script2.2-header.htmlif(!isset($page_title))為了防止有些PHP在包含頁頭文件時可能忘記設(shè)置$page_title,所以在此我們設(shè)置了一個默認(rèn)的頁面標(biāo)題(當(dāng)然可以使用更加明確了錯誤報告,那么在頁面沒有設(shè)置$page_title時,瀏覽器的標(biāo)題會變得很,如圖2-5所示。保存文件為headerhtml。文件的擴(kuò)展名。有些程序員喜歡使用.inc
圖2-5要確保$page_title變量的值已經(jīng)被這是個包含文件,這里我們還可以使用.inchtml作為其擴(kuò)展名,同時表示它既是一個包含文 又是一個HTML文件(以便于和全部由PHP代碼構(gòu)成的包含文件區(qū)分開來。把從頁面特定的內(nèi)容結(jié)束到頁面末尾的內(nèi)容全部到一個新的文件,如2.3<div<divCopyright©colour_blue?<ahref="??HTML5</a>|<a?check/referer">CSS</a>?<a??from?頁腳文件包含頁面的剩余格式,包括頁面的頁腳和結(jié)束HTML文檔的。保存文件為footer.html。將兩個文件都放在Web服務(wù)器的 2.3頁腳文件完成整個HTML模板<!--#Script2.3-footer.html--<div<divCopyright©colour_blue?<ahref="??HTML5</a>|<a?/css-?<ahref="??from索引文件是模塊化程序中的主要,事實上它是唯一會被加載進(jìn)Web瀏覽器的頁面。這種構(gòu)建方法的技術(shù)術(shù)語叫做引導(dǎo)文件(bootstrap?le,它通常也是在基于框架的系統(tǒng)中Web頁面。這可能涉及以???合并HTML模?按照慣例來說,引導(dǎo)文件不會包含任何HTML代碼,因為這些必不可少的HTML代碼在文本編輯器或者集成開發(fā)環(huán)境中新建一段PHP,并命名為index.php,2.4<?php#Script2.4-24索引頁面的控制著一切,它決定應(yīng)該包含哪個模塊、需要的配置文件,并且合并HTML模板 <?php#Script2.4-index.php *Thisisthemain*Thispageincludestheconfiguration*thetemplates,andanycontent-specific8//RequiretheconfigurationfilebeforeanyPHP//Validatewhatpageto $p= $p=}else$p= //Determinewhatpagetoswitch{case$page=$page_title='AboutThiscase$page=$page_title='Contactcase$page=$page_title='Search//Defaultistoincludethemain$page=$page_title='SiteHome //Makesurethefileif(!file_exists('./modules/'.$page))$page=$page_title='SiteHome //Includetheheader//Includethecontent-specific//$pageisdeterminedfromtheaboveinclude('./modules/'.$page); //Includethefooterfiletocompletethe $p=$p=}else$p=}要顯示的內(nèi)容是基于發(fā)送給這個頁面的值。當(dāng)用戶單擊時,這個值會通過URL發(fā)送過來。當(dāng)大部分表單提交時,這個值會通過$_POST發(fā)送。如果不是上述兩種情況之一,腳本就把$p設(shè)置為NULL。switchswitch{case$page=$page_title=每個模塊的文件名稱都是xxx.inc.php,我們用這種方式表示它既是一個PHP,同時也是一個包含文件。根據(jù)計算機(jī)處理擴(kuò)展名的方式,只有最后一個擴(kuò)展名是真正有效的(也就是說,如果直接運(yùn)行這種文件,它會被當(dāng)做PHP來處理。完成switch語句:case$page=case$page=$page_title$page=$page_title}//Endofmain每個可能的內(nèi)容模塊都包含在switch語句中。出于安全的目的,default語句是很重要的。如果$p沒有值或者不是有效值(語句中指定的某個值),就會使用main.inc.php文件。這是必不可少的安全步驟,因為一些用戶在看到站點的URL形如index.php?p=contact的時候會在瀏覽器地址欄中嘗試輸入類似index.php?p=/path/to/secret/?le這樣的內(nèi)容。在這種情if(!file_exists('/modules/'?$page))$page=$page_title='SiteHome}switch語句的每個條件設(shè)置的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 養(yǎng)老院老人生活照顧人員職業(yè)道德制度
- 養(yǎng)老院老人健康數(shù)據(jù)統(tǒng)計分析制度
- 民航安全管理體系培訓(xùn)心得
- 新媒體合伙人合同(2篇)
- 承包采摘黃秋葵協(xié)議書范本(2篇)
- 2024年智能化物流設(shè)備采購合同
- 《食管癌的治療》課件
- 2025年棗莊貨運(yùn)資格證安檢考試題
- 2025年廣州貨運(yùn)從業(yè)資格考試技巧
- 2025年青海貨運(yùn)從業(yè)資格證考試模擬考試題庫
- (高清版)DZT 0368-2021 巖礦石標(biāo)本物性測量技術(shù)規(guī)程
- 在平凡中奉獻(xiàn)在奉獻(xiàn)中堅守
- 食堂出品方案
- 農(nóng)民素質(zhì)素養(yǎng)提升培訓(xùn)
- 【大單元教學(xué)】Unit 8 單元整體教學(xué)設(shè)計
- 安格爾作品欣賞課件
- 保健按摩師-國家職業(yè)標(biāo)準(zhǔn)(2023年版)
- 四川仁壽紅色革命
- GJB9001C內(nèi)部審核檢查表
- 河北省安全生產(chǎn)風(fēng)險管控與隱患治理規(guī)課件
- 氣管切開非機(jī)械通氣病人氣道護(hù)理課件
評論
0/150
提交評論