網頁間的資訊傳遞
本章重點
為什麼HTTP會生生不息地擴散?
GET參數
另一種使用GET風格式樣的URL
處理表單變數
PHP超數組
本章簡單講解一些有關在Web頁面之間傳遞資料的內容。這樣的一些資訊不是PHP特有的,而是PHH/HTML或HTTP協議本身中很重要的部份。
HTTP是沒有狀態紀錄的(stateless)
需要記住有關Web服務一項最重要的事情是,HTTP協議本身沒有狀態紀錄的(stateless)。如果讀者具有詩意的靈魂,可能就會說每個HTTP請求(request)孑然一身,沒有家園,就像一個全然未知的……你知道這之類的說法。對缺乏詩意的我們,說白點就是指每個HTTP請求(每一次的請求和傳送頁面)獨立於所有其它的內容、不知道用戶端身份,而且也沒有記憶。每個請求產生一件獨立過程,完成一件檔案服務、看似微小卻重要的任務,然後自動消失(這樣呼起來很無情,或許可以說成「回到可處理的狀態中」)。
即使把網站設計成非常不嚴格的單嚮導航(頁1引導到頁2,頁2引導到3等等),PTTP協助從來不知道也不關心某個人瀏覽的頁2是否來自頁1。因此,不可以把頁1上的變數設定成透過HTML本身來匯入該頁。可以使用HTML顯示表單,用表單輸入一些資訊,但是除非用一些別的方法把資訊傳送到另一頁或另一個程式,否則一旦移到另一頁,變數就消失了。
這是為什麼匯入像PHP這樣的表單處理技術的原因。PHP可以擷取從一頁輾轉傳到另頁的變數,能對它進行更進一步的動用。PHP函式正好非常擅長這種型態的資料傳遞函式,這樣能更快、更容易地完成各種Web網站的任務。
HTML表單是網站上用來由一個網頁傳遞一些資料最有用的方法,有許多更持久的方式可以維護橫跨許多網頁的狀態方法,例如cookie與session,我們會在第27章介紹這些功能。本章會著重在更基本的技術巧用來傳遞網頁之間的資訊,就是使用HTTP和GET與POST方法來進行動態產生網頁以及處理資料。
ASP程式設計者看到這裡可能要說「PHP真爛!」因為他們讓為ASP的session變數是非常神奇的。這不是要截破誰的泡泡,而是微軟正打算利用cookie來儲存session變數,不過這樣就開啟了所有潛在問題的大門。
GET參數
GET方法把參數當成URI [Uniform Resource Indicator,一致資源指標;也有人更習慣用URI (Uniform Resource Indicator,一致資源定位器)]查詢字串的一部份,從一個頁面傳遞到另一個頁面。當用於表單處理時,GET用問號(?)當成分隔字元號把變數名稱和值附加給在ACTION屬性中來反指定的URL,並把所有內容提交給提供處理的技術(在這個例子中是Web伺服器)。
這是一個使用GET方法的HTML表單範例(把檔案存在team_select.html):
< HTML >
< HEAD >
< TITLE >A GET example, part 1< /TITLE >
< /HEAD >
< BODY >
< FOPM ACTION = http://localhost/baseball. php METHOD = “GET” >
< P >Root, root, root for the :< BR >
< SELECT NAME = “Team”SIZE=2 >
當使用者進行選擇並按一下Submit按鈕時,瀏覽器按照下面的順序把這些元素接合、一起,中間不會有空格:
在單字ACTION後面,括在引號中的URL(http://localhost/baseball.php)
問號(?)指示以下字元即會組成GET字串
NAME變數、等號、以及配合的VALUE(Team = Cubbies)
「&」符號和下一對「NAME = VALUE」(Submit = Submit);只要伺服器查詢字串的長度限制允許,這些使用&區隔的name – value組合可以被重複許多次。
這樣會構成這樣一個URL字串:
(http://locahost/baseball .php ? Team = Cubbies&Submit = Select)
其中字串成為新的請求傳送到瀏覽器的地址空間。上面的表單提交後,處理表單的PHP script(baseball.php)將從請求字串的尾端取得GET變數,並對這些變數進行相對應的操作,在下面這個例子中,是把兩個值中的一個插入文字字串中。
以下程式碼是PHP用來處理原先HTML表單的表單處理部分:
< HTML >
< HEAD >
< TITLE >A GET example ,part 2< /TITLE >
< STYLE TYPE = “text/css”>
< !--
BODY {font-size: 24pt;}
-- >
< /STYLE >
< /HEAD >
< BODY >
< P >Go,
< ?php echo $_GET[‘Team’];? >
!
< /BODY >
< /HTML >
最後你應會看見網頁上呈現大字樣的Go,Cubbies。
表單處理中的GET方法有一個比POST方法好很多的優點:它建立了一個真正新的、完全不同的URL查詢字串。如此一來使用者就可以把這一頁記為書籤(當開發小組意志消沈時,看到這個就能鼓舞士氣了)。從使用POST方法的表單取得到的結果是不能記成書籤的。
然而,你可以用GET參數完成想要的功能不代表你應該使用,對於大多數表單處理程式,GET方法的缺點實在是太嚴重了,以致於最初的HTML 4.0正式規格不贊成使用它。這些缺點包括:
GET不適合用於登入(login),因為把使用者名稱和密碼當成存取過的面潛藏儲存有使用者端瀏覽器的記憶體中時,在螢幕是也是完全可看見的。
每個GET提交都被記錄在Web伺服器log中,資料集也包括在內。
因為GET會分配資料到伺服器環境變數,所以URL的長度有受到限制。你可以想象使用GET時非常長的URL是長什麼樣子,不過事實上誰也不想用這種方法嘗試傳遞三百字的HTML格式的文章。
初使的HTML正式規格中對查詢的字串長度的限制是255個字元,雖然後來放寬了對255個字元的限制,但是使用很長的字串真的是自尋煩惱。
在進行過很多爭論後,W3仍然恢複使用表單處理中的GET方法,主要是由於書籤功能的因素。雖然GET方法仍然是表單處理的預設選取項,但我們還是建議你只把它用於沒什麼副帶作用於的地方。把兩個優點和兩個缺點放在一起考慮思量一番,使用GET處理表單的最適合的用途其實應該是「搜尋方塊(search box)」。除非迫不得已的原因才把GET方法用在非搜尋性的表單處理程式,不然你就使用POST方法替代。
一種更好的GET風格URL用法
雖然對錶單處理GET方法已經被建議不採用了。但是和它相關的URL風格對於網站的導航還是非常有用的,尤其適用於動態廣告的網站,例如那些經常用PHP建構的網站,因為附加了變數格式的URL,就非常適合以樣版當基礎的內容發展系統。
有如下例所示,假設你所經營的是一個關於太陽能汽車資料豐富的Web網站,而你已將冗長且一致格式的資料豐富與誘有頁面存放如下:
suspension_design.html
windtunnel_testing.html
friction_braking.html
但是當網站規模增大時,如此簡單的檔案網站結構就要耗費很多時間進行管理,因為一些瑣碎的變動都必須在每個頁面上重複進行。如果這些頁面的結構非常簡單,就可以用PHP把網站轉換為以樣版基底的系統。
你可能決定用一個單一的樣版來將每一個主題的文字檔案區分(包括資訊、照片、意見,等等):
topic.php
suspension_design .inc
windtunnel_testing . inc
friction_braking . inc
或是你可能決定一個更大、更為特殊選擇處理的樣版檔案:
vehicle_structure . php
tubular_frames . inc
mechanical_systems . php
friction_braking . inc
electrical_systems . php
solar_array . inc
racing . php
race _strategy . inc
一個簡單的樣版可能有如此例所示(因為我們未含括所需的 .inc文字檔案,這個檔案將無法實際運作):
< HTML >
< HEAD >
< TITLE >Solar – car topics< /TITLE >
< STYLE TYPE= “text/css” >
< !-
BODY{font:verdana;font – size:12pt}
-- >
< /STYLE >
< /HEAD >
< BODY >
< TABLE BORDER = 0 CELLPADDING = 0 WIDTH = 100% >
< YR >
< !—Navbar,with Get-style URLs .-- >
< TD BGCOLOR = “#4282B4” ALIGN = CENTER VALIGN=TOP WIDTH=25% >
< P >
< A HREF=“mechanical_syatems .php? Name = friction_braking”>< B >Friction braking< /B >< /A >
< BR >
< A HREF = “mechanical_syatems.php?Name = steering” >< B >Steering< /B >< /A >
< BR >
< A HREF = “mechanical_systems .php ? Name = Suspenion” >< B >Suspenion< /B >
< /A >
< BR >
< A HREF = “mechanical_systems .php ? Name =tires” >< B >Tires and wheels< /B >
< /A >
< BR >
< /P >
< /TD >
< !—Main body of content - - >
< TD BGCOLOR = “#FFFFFF” ALIGN = LEFT VALIGN=TOP WIDTH = 75% >
< ?php include(“$_GET[‘Name’].inc”)? >
< /TD> < /TE >< /TABLE >
< /BODY >
< HTML >
請注意,當被按一下時導航列上的串連會被瀏覽器處理,就像是提交一個GET處理一樣。
但是對於這個處理方案,仍然必須手動更改一部份程式碼:以確保每個被包含進去的檔案都是正確的HTML格式,每次給網站增添新頁面時讓導航列加入新的串連,以及其它類似的內容。儘可能按照一般常規把表單和內容分開,你可以選擇使用資料庫。若使用資料庫,URL就會類似如下:
(http://localhost/topic .php ?topicID = 2)
它將指向某個處理資料庫呼叫的PHP樣版(使用數字變數而不是使用單字可以更快地查詢資料庫)。當給資料庫新增新的主題時,該系統會幫導航列加入連結,所以不用手動就可以產生所有的Web頁面(這裡的「所有」一詞是有些誇大了,但是的確可以省去人員與時間的多餘勞力)。
POST參數
POST是目前相對好的表單處理方法,尤其適合需要不是一次使用完的情況(指定長期配合處理的一些資料或作用),例如在為資料庫添加資訊的處理。當表單資料被傳送到處理常式(在這裡指PHP)時,被包含在表單本體內。提交的資料不同時,在URL中看不出什麼變化。
POST方法有以下這些優點:
◎ 它比GET更安全,因為在URL查詢字串、伺服器log中,或在螢幕上(如果採用了預防措施,例如總是使用HTML的password輸入格式來表達密碼欄位)看不到使用者輸入的資訊。
◎ 對能被傳遞的資料的數量限制更寬鬆了(可到二千個元組,而不只是二百多個字元)。
不過POST也有一些缺點:
◎ 其結果不能被標記為書籤。
◎ 這種方法和某些防火牆設定不相容,為了安全上的考慮,防火牆會去掉某些表單資料。
在本書中我們一致使用POST方法來處理表單,尤其在使用寫入檔案或INSERT的SQL文法將資料填入系統時。我們只在網站的瀏覽與搜尋方塊才會使用GET的方法,換句話說,使用時機分別為將資料寫到資料儲存位置以及顯示網頁,本章其餘表單皆會使用POST方法。
同時使用GET和POST方法
你知道嗎?PHP允許在同一頁上同時使用GET和POST變數,因此可以自在地編寫動態表單!
但是這樣立刻引發一個問題:如果在GET 和POST陣列中(故意或由於其它原因)使用同樣的變數名稱會怎麼樣呢?如果你將你的php .ini檔案內的register_globals指令設定為on的話,PHP把ENVIRONMENT、GET、POST、COOLIE與SERVER 等變數存放在$GLOBAL陣列中,如果產生衝突的話,它會根據你所設定的順序來重新調整變數內容來解決,藉由你在php .ini內的變數_order選項設定。較後者會取代前者,所以如果你使用預設的“EGPCS”值的話,POST會取代GET,COOKIE會取代 POST,你可以藉由在這個檔案內適當調整字母的順序來控製取代的順序,或是甚至最好將register_globals關閉並使用PHP新的超全域陣列,我們會在以下部分介紹。
在PHP中的變數處理
PHP對於傳遞資料非常有效率是因為開發人員決定使用一項很方便但(在理論上)有點複雜的設計。當使用GET或POST方法提交資料集時,PHP會自動擔以看不見的方式為新頁面上的變數地行指定。其它大多數的程式語言讓程式設計者自己在頁面上執行明確顯生的指定處理;如果忘記指定或寫錯了,則資訊就不能傳到處理代理程式中。相較之下,PHP更快、更簡單,更能防呆。
但是由於這樣的自動變數指定,你必須永遠為每個INPUT控制項取一個好的NAME屬性,其實NAME屬性並不是HTML強制需要的,你的表單即使少了它仍可以運作正常,但是資料將會沒有任何功用,因為這些HTML的NAME表單欄位屬性將是表單處理程式的變數名稱。
換句話說,以下的表單:
< FORM ACTION = “< ?php echo $_SERVER[‘PHP_SELF’]; ? >” METHOD =“POST” >
< INPUT TYPE=“text”NAME=“email” >
< INPUT TYPE=“submit”NAME=“Submit” VALUE=“Send” >
< /FORM >
email文字欄位將會使得當表格傳送時PHP產生變數為$_OPET[ ‘email’](或是如果你使用舊式的陣列變數則為$ HTTP_POST_VARS[ ‘email’],甚或是你將register_globals啟動則為$email),同樣的,傳送按鈕會使得下一個網頁產生$_POST [‘submit’]變數,你在HTML表單所使用的名稱將會成為你PHP表單處理的變數表單欄位。
另外一個產和生HTML表單必須記住的就是如果你希望表單在填寫之前顯示初始字樣的話,你必須設定VALUE屬性,這特別有用在兩種類型的表單上:用來將資料輸入資料庫的表單,以及用來傳送超過一次的表單,其中後者常常出現在表單需要在出現填入錯誤時重新顯示表單的情形,例如,一個用來登入的表單會直到使用才輸入有效email地址或是其它相關資料才能送出。
例如,以下的表單(用來當作退休金試算表)被設計為當使用者填入資料時可以傳送多次,每當你傳送表單,你前一次所填入的次料會自動填入,請注意以下程式範例表單欄位的VALUE屬性。
< HTML >
< HEAD >
< TITLE >A POST example:retirement savings worksheet< /TIELE >
< STYLE TYPE = “text.css” >
< !- -
BODY {font-size:14pt}
.heading {font-size:18pt; color:red}
-->
< /STYLE >
< /HEAD >
< ?php
//This test,along with the Submit button value in the form below,
//will check to see if the form is being rendered for the first time
//(in which case it will display with only the default annual gain
//filled in )
If (!IsSet($_POST[′Submit?])||$_POST[′Submit?]!=′Calculate?){
$_POST[‘CurrentAge’] = “”;
$_POST[‘RetieAge’]= “”;
$_POST[‘Contrib’]= “”;
$Total = 7;
}else{
$AnnGain = $_POST[‘AnnGain’];
$Years = $_POST[‘RetireAge’] - $_POST[‘CurrentAge’];
$YearCount = 0;
$Total = $_POST[‘Countrib’];
While($YearCount<= $Years){
$Total = round($Total *(1.0 + $AnnGain/100)+$_POST[‘Contrib’]);
$YearCount = $YearCount+1;
}
}
? >
< BODY >
< BIV ALIGN = CENTER ID = Divl class = heading >A retirement – savings calculator
< /DIV >
< P class = blurb >Fill in all the values(except “Nest Egg”)and see how much money you′ll have for your retirement under different scenarios.You can change the values and resubmit the form as many times as you like.You must fill in the two “Age”variables.The “Annual return” variable has a default inflation-adjusted value (7% = 8% growth minus 1% inflation)which you can change to reflect your greater optimism or pessimism.< /P >
< FORM ACTIIN = “” METHOD=“POST” >
< P >Your age now:< INPUT TYPE=“text” SIZE= 5 NAME=“CurrentAge”VALUE=“” >
< P >The age at which you plan to retire:< INPUT TYPE = “text”SIZE=6
NAME = “RetireAge”VALUE = “< ?php echo $_POST[‘RetireAge’];? >” >
< P >Annual contribution:〈 INPUT TYPE=“text” SIZE=15 NAME=“Contrib“ VALUE=“ < ?php echo $_POST[?Contrib?]; ? > “ >
< P > Annual return: < INPUT TYPE==“text”SIZE=15 NAME=”AnnGain ”VALUE= ”< ? php echo $annGain; ? > ” > %
< BR >< BR >
< P >< B >NEST EGG< /B >:< ?php ECHO $Total;? >
< P >< INPUT TYPE=“submit”NAME=“Submit”VALUE=“Calculate” >
< /FORM >
< /BODY >
< /HTML >
圖9-1顯示上述程式的結果.
圖9-1:使用方法與VALUE屬性的表單
強化表單與表單處理
如同你可以在上述程式所見,通常將HTML表單與表單處理程式放在同一個程式是簡易的,這樣的方式有許多優點,例如,你的登入網頁將會在登入失敗時顯示錯誤訊息,如果你將表單處理程式分開的話,你可能還需額外藉由GET變數來重新轉址,如果你強化表單運作的話,你可以更加簡易的控制顯示而不需使用如此的機制。
當你強化表單的時假,表單處理程式應該出現在表單顯示之前,有人可能會讓為因為先設計表單才處理常式所以應該將順序顛倒,但是如果你按照這裡的方式,你便會瞭解其間的邏輯,你必須使你能夠先將變數名稱取好並且在顯示表單之前做選擇,這對如果你在某些情形必須將使用者導向不同的網頁,藉由使用header ()函式,更重要的,因為這個決定必須在任何HTML輸出顯示在瀏覽器之前就變成了。
以上就是PHP學習寶典-第九章的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!