首頁  >  文章  >  後端開發  >  PHP表單詳解

PHP表單詳解

WBOY
WBOY原創
2016-07-29 09:09:051870瀏覽

提到Web開發,就不得不提到HTML,它在若干年以來一直是Web使用者介面設計的事實標準。雖然現在WAP/XML等頁面腳本的使用使得 HTML作為一枝獨秀的情況難以維繫,但是如果要編寫前端PHP的Web應用,開發者仍然需要了解HTML語言,尤其是HTML的表單部分。
在本章,我們將學習以下內容:
? 使用Dreamweaver設計HTML表單
? 使用PHP發送與接收表單資料
? PHP表單多頁的傳值及處理
? 使用PHP驗證使用者輸入
? 在PHP中防止一些輕量級的攻擊
? PHP的兩種會話管理方式:COOKIE和SESSION
? 規劃我們的Web應用程式
5.1 表單與HTML
HTML是一種簡單的標記語言,為使用者提供了極大的靈活性,這一點使它很容易學習和編寫,也同樣是由於這一點,太多的網頁設計人員對HTML的設計與編碼幾乎為濫用,導致一個頁面在IE、Firefox、Mozila幾個不同瀏覽器中顯示得千差萬別。
現今的Web設計已經啟用新的標準,旨在使網頁的HTML只包含內容和訊息,以標準HTML和CSS(級聯樣式表)儲存資訊的方式,也就是現在流行的DIV+CSS設計標準。
有一些人建議使用XML來取代HTML語言。雖然XML有這樣那樣的強大功能,不過因為入門的門檻較高,讓人望而生畏,而且目前有太多的HTML型網站,因此目前沿行的標準是HTML與XML的兼容規格,叫做XHTML,用以從HTML過渡到XML。在本書中的程式碼都是基於XHTML相容性的,建議 你也將XHTML應用到Web專案中。建立和處理表單是PHP開發者的重要能力指標。下面我們開始介紹如何設計表單。
表單是Web應用中最常用的元件,由提交按鈕以及其他相關元素組成。表單被應用在各個領域中,用於實現註冊用戶、填寫銀行帳戶和登入等功能。
表單使用
作為開始標籤,以
結尾,否則將不起任何作用。在一個HTML頁面中允許有若干個表單,在編寫時以表單的名字(name)和Form ID作為它們之間的區分。
下面是最簡單的表單,程式碼如下:




這個表單在瀏覽器上只會顯示一個按鈕「提交查詢內容」字樣,沒有太多的意義。如果要提交資料並形成一個完整的表單,需要在
標籤增加兩個比較重要的屬性標籤:action和method,如以下表單所示:

    電子郵件:
   

其中,action標籤指的是接收處理結果的文件位置,當action值為空時,則提交給當前文件本身,如果action的值為其他文件或URL,則提交給該文件或URL地址處理。
method標籤是描述提交資料時使用的方法,它有兩種值:GET和POST,如果沒有設定method屬性或該屬性為空值,瀏覽器預設method的值為POST方法。
下面是處理POST表單的方法。
例5-1:getPasswd.php – 接受POST表單提交的值
$action = $_SERVER['PHP_SELF'];     
if ($_SERVER['REQUEST_METHOD'] == 'POST')  echo '使用POST方法傳遞表單值';
    echo "$_POST[email]";
}
?>     

    電子郵件:
   

如果要在瀏覽器中傳送表單或資料給伺服器端,使用GET或POST方法都能實現。 GET方法是在存取URL時,使用瀏覽器網址列來傳遞值。我們可以在很多網站上看到這類URL串,圖5-1所示的就是使用GET方法傳遞參數。
 
                                           圖5-1
GET方法方便直觀,缺點是訪問網站的使用者也可以修改URL串後發送給伺服器,如果程式處理得不夠好很容易出錯,而且GET傳遞的字串長度不能超過250個字符,如果超長,瀏覽器會自動截斷,導致資料缺失。另外,GET方法不支援ASCII字元以外的任何字符,例如包含漢字或其他非ASCII 字元時,需要使用額外的編碼操作,雖然有時候瀏覽器也能自動完成(可以使用url_encode和url_decode函數,使用方法詳見2.9.2 節)。
POST方法發送變數資料時,對於使用者來說是不透明的,按HTTP協定來說,資料附加於header的頭資訊中,使用者不能隨意修改,這對於Web應用程式而言,安全性要好得多,而且使用POST可以傳送大體積的資料給Web伺服器。
因為POST是隨HTTP的header資訊一起發送的,當觸發POST表單提交後,如果使用者瀏覽頁面時點擊「後退」按鈕,瀏覽器不會自動重發 POST資料。如果使用者此時點選「刷新」按鈕,將會有「資料已經過期,是否重新提交表單」的提示,這一點不如GET使用方便。使用GET傳值時,即便使用者 使用「後退」或「刷新」按鈕,瀏覽器的URL位址也是仍然存在的。
因此,我們在開發中需要根據實際應用靈活選擇GET和POST來提交表單資料。
值得一提的是,如果在HTML中缺少表單結束標記,那麼整個表單是不會觸發任何提交動作的。在實際開發時,一些粗心的人會發現單擊按鈕沒有任何反映,其實細心檢查一下表單的代碼就可以了,有時即使少寫了一個HTML字符,瀏覽器也不會替我們幹活的。
5.4 表單元素
表單所使用的標籤元素有十幾個,PHP開發中常用及較重要的標籤如表5-1所示。
表5-1
表單元素說   明
input type="checkbox"複選框,允許使用者選擇多個選擇項
input type="file"檔案瀏覽框,當檔案上傳時,可用於開啟一個模式視窗以選擇檔案
input type="hidden"隱藏標籤,用於在表單中以隱含方式提交變數值 
input type="password"密碼文字框,使用者在該文字方塊輸入字元時將被替換顯示為*號碼
input type="radio"單選項,用於設定一組選擇項,使用者只能選擇一個
input type="reset"清除與重設表單內容,用於清除表單中所有文字方塊的內容,而且讓選擇選單項目恢復到初始值
input type="submit"表單提交按鈕
input type="text"單行文字方塊
select下拉列錶框,可單選和多重選取。預設為單選,如果增加多項選擇功能,增加
其中,hidden標籤被稱為隱藏或隱含的標籤,它不會在使用者瀏覽的頁面介面上出現,當使用者填寫資料表單和跨頁之間傳值時,可以使用該標籤傳遞一些隱含的值。
password密碼文字方塊用於隱藏密碼,使用者輸入的文字將以*顯示在文字方塊中,但是密碼並沒有加密,只是被*替換顯示,這點請注意。
下面介紹表單的屬性,它們用於表單中約束表單元素的行為或顯示,其意義與限制如表5-2所示。
表5-2
屬性名稱說   明
name文字方塊的名稱,PHP根據該名稱,在超級全域數組中建立以name為名稱的鍵名
size文字方塊的寬度,在select下拉式選單中,表示可以看到的選項行數
value文字方塊中的預設值,注意,該值不能應用到type=password密碼文字方塊以及type=file檔案文字方塊中
multiple此屬性用於下拉清單選單select中,指定該選項使用者可以使用Ctrl和Shift鍵進行多選
rows多行文字方塊顯示時可以容納的字元列數寬度
cols多行文字方塊顯示時可以容納的字元行數高度
除了以上一些必要的屬性元素外,還有一些標準屬性,如class,style,id等,可以參考HTML相關資料。
在一些動態腳本中,需要使用PHP根據不同的請求從資料庫產生表單元素,下面我們就來展示幾種產生表單按鈕或選項的方法。
1.動態產生一組單選按鈕。
$options = array("010" => "北京",
                  "020" => "上海",
="                "0411" => "大連");
$default = "024";
$html = generate_radio_group("city_id", $options, $default);
echo $html;
function generate_radio_group($name, $options, $default="" name {
= htmlentities($name);
foreach($options as $value => $label) {
    $value = htmlentities($value);
    $html .= "    $html .$ value == $default){
      $html .= "CHECKED ";
    }
    $html .= "NAME="$name" VALUE="$value">";
 >";
}
return($html);
}
?>
此腳本將產生一列單選按鈕組,名稱為city_id,預設選項為024-「瀋陽」 。
2.動態產生多選項下拉清單選單。
function generate_checkboxes($name,$options, $default=array()) {
if (!is_array($default)){
    $default = array();
}
(    $default = array(); value => $label) {
     $html .= "     if (in_array($value, $default)){
     $html . name="{$name}[]" value="$value">";
    $html .= $label . "
";
}
return($html);
}
$interests = array( "音樂" => "音樂",
                  "電影" => "電影",
               旅遊");
$html = generate_checkboxes("interests", $options, $interests);
?>
選擇您的嗜好:




3.產生多選下拉清單選單。
$options = array(
        '1' => '請選擇',
        'news' => '新聞',  1       'news' => '新聞',
);
$default = "news";      //預設已選取的項目
$html =generate_muilti_option("select", $options, $default);
echounchtml;
ftion geneoprate_muil_chounchtml; $default){
    //建立一個允許多重選擇的清單單
    echo '';資料庫取得資料或資料數組,轉換成動態HTML選單,也可以手動建立.
5.5 表單的處理方法
5.5.1 檢查表單提交的來源
有些時候,我們需要對表單提交的來源進行處理,例如只允許某個主機或向腳本本身提交,防止有的人偽造相同的表單向我們的程式提交,造成安全問題。
前面我們介紹到,PHP的$_SERVER伺服器超級全域數組提供了一個叫做$_SERVER['HTTP_REFERER']的變量,用於保存上一 頁的來源,例如表單提交或超級連結的URL位址。如果有人從他的電腦提交表單或從瀏覽器位址直接輸入當前腳本名稱,則該變數會保存表單來源或為空 值,這樣我們就可以透過它的值進行處理。
下面的範例只允許檔案本身提交表單傳遞值。
例5-2:formreferer.php – 判斷表單來源位址
$action = $_SERVER['PHP_SELF'];
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
 = $_SERVER['HTTP_REFERER'];
    $srv = "http://{$_SERVER['SERVER_NAME']}$action";
    echo "目前來源為:
$ref -------------------------------------------------- ------------------------------
";
    if (strcmp($srv, $ref) == 0){
echo "匹配";
    }   else{
        echo "不允許站外提交";
    }
}else{
    echo '請提交表單'; ?>" method="post">


該例中用到的$_SERVER伺服器變數有以下幾個:
? HTTP_REFERER 保存一個完整的來源URL位址。
? SERVER_NAME 目前的伺服器名稱。
? PHP_SELF 目前腳本的完整路徑,包括檔案名稱。
我們可以透過「http:// == 」來比較,如果相同,則是合法的表單提交,否則不予處理。執行例5-2腳本,點選「提交」按鈕後的結果如圖5- 2所示。
 
圖5-2
5.5.2 一個完整表單處理
前面我們已經了解了處理表單的簡單方式。下面我們將建立一個複雜的表單,程式碼如下所示。



    > ;


    密碼:
   



   

;
   
   


   


  發展語言: 
   


   


   
   

   
年齡:
     
16」>小於16選項>
      16-30選項>
      ;31-50選項>
      51-80選項>
        
   
自我介紹:

gt;
體育嗜好:
   

網球
   
足球

籃球

保齡球

     
php

java

perl

c++

.NET

delphi


      開發工具:
   

Zend Studio選項>
      Eclipse選項>
      Editplus選項>
      Ultraedit選項>
      Ultraedit選項>
      其他選項
 


此表單包含常用的表單元素:單行文字方塊、多行文字方塊、單一選項(radio)、多重選項(checkbox),以及多選菜單。下面進行詳細的說明。
? maxlength是與密碼文字方塊關聯的屬性,它限制使用者輸入密碼的最大長度為10個字元。
? age列錶框是清單選單,它的命名屬性下都有自己的值可供選擇。 selected是特定的屬性選擇元素,如果某個option附加有該屬性,顯示時就把該項列為第一項顯示。
? intro文字方塊中的內容,依照rows和cols顯示文字、行和列寬。
? fave_sport是一組單選按鈕(radio),我們要按組命名元素名稱,例如這一組單選按鈕都叫做fave_sport,用戶只可選擇一個,發送腳本端也只存在一個值。
? 和單一選項一樣,所有多選項成員也須有同名的屬性,而屬性名稱需要加括號[],這樣就把多選項的值以數組形式發送給PHP,languages就是這種形式。
? checked標籤是指單選項和多選項中的某個值,預設已經被選擇。
上面表單的顯示畫面如圖5-3所示。
 
圖5-3
因為上面HTML中的form表單使用的是POST方法傳遞數據,所以用戶提交的數據會保存到$_POST或$_REQUEST的超級全域數組中,我們根據$_POST數組中的值就可以處理提交的資料。
將上面表單中資料提交到someform.php腳本,該腳本的處理邏輯如下:
//透過判斷按鈕的變數名稱是否在$_POST中定義,如果有表示表單已提交
if( isset($_POST["btn_submit"])){
    if (empty($_POST['username'])){
        echo "您沒有輸入用戶名"; $_POST['password'])){
        echo "您沒有輸入密碼: ";
        exit(0);
    }
  user echo "您的使用者名稱: ".$_
    echo "您的密碼(明文): ".$_POST['password']."
";
    echo "您的年齡: ".$_POST['age']."
" ;
    if (!empty($_POST['languages'])){
           echo "您選擇的語言為:";
        //處理使用者選擇的語言為:";
        //處理使用者所選擇的語言為:";
     . ] as $lang){
           echo $lang. "  ";
         }
    }  !empty($_POST['develop_ide'])){
echo "您使用的開發工具為:";
        //處理使用者多重選擇開發工具選單產生的陣列
        foreach ($_POST['develop_ide'] as $ }
} else {
        echo "您沒有選擇開發工具";
    }
    echo "您的自我介紹: ".nl2br($_POST['intro'])."
";
($_POST['intro'])."
";
透過hidden標籤值傳遞): ".$_POST['from']."
";
}
?>
說明:使用POST方式提交表單,透過HTTP協定的header部分傳遞表單數據,理論上數據的大小無上限。不過,在使用PHP進行POST提交時,檔案大小受PHP設定檔(php.ini)限制,我們可以修改php.ini檔案中的post_max_size參數,可將預設的2M位元組,修改為自己需要的大小,但由於HTTP協定的特性,這個值不宜設定過大,最大以8M為宜。
5.6 其他處理表單的方法
下面,讓我們一起來看兩種處理表單的程式設計方法以及它們的優缺點。
5.6.1 使用import_request_variables()函數
使用import_request_variables()函數可以選擇性地註冊全域變數集合。你可以使用函數匯入 $_GET、$_POST和$_COOKIE的值,也可以為每個匯入的變數加上前綴(prefix)。
bool import_request_variables ( string types [,string prefix])
參數中types字串中允許為g、p、c字符,或3個字符間任意的組合。其中,「g」表示GET變量,「p」表示POST變量,「c」表示cookies。
注意:3個字元的排列順序是有區別的,當使用「pg」時,POST變數會使用相同的名字覆蓋$_GET變數;反之,當使用「gp」時,$_GET變數陣列將優先於$ _POST。
prefix參數作為變數名稱的前綴,置於所有被匯入到全域作用域的變數之前。例如我們有一個名為「userid」的$_GET超級全域變數數組,同時 提供了「pref_」作為前綴,那麼我們將會得到一個名為$pref_userid的全域變數。如果我們要匯入其他全域變數(例如$_SERVER變數), 則請考慮使用extract()函數(在函數章節中有介紹)。注意,在使用prefix前綴時,請勿與現有資料或變數名稱產生衝突。
使用import_request_variable()函數實作變數匯入的腳本範例如下:
//匯入POST提交的變數值,前綴為post_
import_request_variable("p", "post_");
//導入GET和POST提交的變數值,前綴為gp_,GET優先於POST
import_request_variable("gp", "gp_");
//導入Cookie和GET的變數值,Cookie變數值優先於GET
import_request_variable("cg", "cg_");
如果我們在import_request_variables()函數中使用了“pg參數”,請看如下腳本實例:
if(isset($_REQUEST['btn_submit'])){
echo "正常取得的表單POST變數值:".$_REQUEST['U​​sername']."
";
import_request_variables("pg", "import_");
//顯示導入的變數名稱
echo "使用import_request_variables導入函數的變數值: ".$import_Username;
}
?>

請輸入您的名字:


該表單提示使用者輸入一個名字,完成並提交後,腳本會把提交的名字顯示在瀏覽器上,如圖5-4所示。
 
圖5-4
注意:prefix前綴參數是必選的,如果未指定前綴,或指定一個空字串作為變數前綴,PHP會拋出一個E_NOTICE錯誤。
import_request_variables()函數為我們提供一個中間方法,適用於下列情況:
1.當使用者無法使用超級變數數組時;
2.在php.ini設定檔的register_globals參數為Off(PHP 5之後的版本預設為Off)時,使用import_request_variables將GET/POST/Cookie這幾個超級變數陣列匯入到全域作用域中。
3.在開發時,只要宣告了引入的變數範圍,就不必寫$_GET或$_REQUEST一堆很長的超級全域數組名稱了。
5.6.2 使用extract()函數
我們可以使用extract()函數,例如在接收頁面腳本的最前面加上extract($_POST);extract($_GET);這樣的語句,導出幾個用於表單處理過的超級變數數組值,如下列程式碼所示:
@extract(i_addslashes($_POST), EXTR_OVERWRITE);
@extract(i_addslashes($_GET), EXTR_OVERWRITE);
@extract(iVERs)@extract(i_adds),$ );
@extract(i_addslashes($_SESSION), EXTR_OVERWRITE);
我們看一個使用extract導出為正常變數的腳本範例:
    // 將$_GET和$_POST超級變數所取得的變數轉為正常的變數,這樣直接顯示變數名稱即可
    extract($_GET);
    extract($_POST);   
    echo "您好, $username $age";
?>
    echo "您好, $username $age";
?>

姓名:
年齡:

當多個頁面傳遞資料時,我們可以使用類似上面的語句來處理前京都市網www.bj135.com@Vogate.com" STYLE="border-bottom: 1px dotted rgb(255, 51, 102); font-size: 1em; cursor: pointer; color: rgb(255, 51, 102); text-decoration: underline;" HREF="http://action.gate. com/c/c.php?r=http%3A//www.ec80.cn/html/05/n-1705-6.html&aid=5526&sid=6235007045042472&click=1&url=http%3A//www.bj135.com&v= 0&s=http%3A//www.ec80.cn/html/05/n-1705-7.html&rn=561758&k=%u4E00%u9875" TARGET="_blank">一頁或透過URL傳遞的值。
5.7 多頁間傳遞資料
當遇到一個非常大的表單時,不可能把所有的表單都放在一個頁裡面,需要將一個大表單分解成若干個小表單,並保存於幾個頁面中,當第一個表單填寫完後,需要收集該表單的值並將其傳遞給下一個表單頁面。
我們可以使用以下方法來處理。
? 使用表單的隱含元素(hidden)。
? 把目前表單的資料保存在SESSION中(詳情請參閱會話一章)。
? 把目前表單的資料保存在MySQL資料庫中。
你可以從以上三個方案中選擇一個易於程式處理和調試的解決方案。表單的傳值可以使用POST,這樣傳遞資料的尺寸不成問題,另外,在偵錯程式時,我們可以透過查看HTML來源檔案方式,來知道目前的變數是否是預想的值。
對於一個非常大的表單,我們就要想辦法把它們分解成兩個或更多個表單以方便用戶輸入,這需要在頁間傳值,代碼如下:


當多個頁面傳遞資料時,我們可以使用類似上面的語句來處理前一頁或透過URL傳遞的值。
5.9 表單安全
網站的訪客是千差萬別的,他可能是一個學生,也可能是一位教授,可能是一個什麼都不懂的電腦菜鳥,更有可能是個黑客,不管是彈出意外的錯誤,還是故意找碴,他們總是喜歡不按我們希望的方式輸入,或尋找我們網站的安全漏洞。
網站中一些常見漏洞,很多原因是開發者的大意造成的,當然還有一部分原因是因為作業系統或伺服器配置的原因。常見的安全隱憂與比例如表5-4所示。
表5-4
程式缺陷比    例
使用者輸入不做驗證42.60%
存取控制缺陷3.60%
SESSION ID驗證漏洞5.40%
資料庫注入28.60%

以上就介紹了PHP表單詳解,包括了方面的內容,希望對PHP教學有興趣的朋友有幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn