要讓前端的表單能跟後端的 PHP 互動,我們要透過 form 標籤的 action 屬性,來指定表單要送出到哪支 PHP 檔案來處理;同樣是 form 標籤的 method 屬性,則是用來指定送出的方法;而 input 等輸入框相關標籤的 name 屬性,則是讓 PHP 認得該輸入框並且取得其值。其中,method 的部份分為 get 和 post 兩種,說明如下:
- get: 會附帶在網址連結當中送出,例如 http://example.com/test.php?abc=123,其中的「abc=123」就是送出的資料。用此方法送出時,資料長度較為受限。
- post: 嵌在封包內部送出,可允許較大量的資料。
以下是利用 get 方法送出資料的範例,此範例會接受兩個整數並相加。其中需要留意,雖然 HTML 不分大小寫,但是 PHP 跟 JavaScript 都一樣會區分,因此 name 屬性的值請注意大小寫。
<html><head></head> <body bgcolor="#ccccff"> <?php if( isset($_GET['a']) && isset($_GET['b']) ){ echo (int)$_GET['a'] + (int)$_GET['b']; } ?> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="get"> <input type="text" name="a"> + <input type="text" name="b"> <input type="submit"> </form> </body></html>
在上述範例中:
- 「isset」可以檢查變數是否存在,以使得在網頁沒有資料輸入(例如初次被存取)時,不需要執行相關運算。不過「isset」只會在變數未宣告、未定義或者值為 null 時回傳 false,如果需要判斷是否為空字串,必須使用「== ""」或者「empty」來進行。
- 「$_SERVER['PHP_SELF']」會取得頁面在伺服器上的路徑,相當於 http://example.com/a/b/c.php 當中的 /a/b/c.php;而 basename 相當於取得主檔名,即前述的 c.php;因此,兩者綜合起來並設定為表單 action 時,相當於將表單資料送到目前的檔案來處理。
- 雖然在運算加法時,只要使用者輸入的是數字,PHP 也會幫我們自動轉型;但是明確的做轉型,可以避免掉萬一輸入不是數字的時候,可能會產生的一些問題。
若要改用 post 送出資料,則只需把表單送出和 php 接收的部份,都改成 post 所需的用法:
<html><head></head> <body bgcolor="#ccccff"> <?php if( isset($_POST['a']) && isset($_POST['b']) ){ echo (int)$_POST['a'] + (int)$_POST['b']; } ?> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="post"> <input type="text" name="a"> + <input type="text" name="b"> <input type="submit"> </form> </body></html>
如果有多個送出按鈕,需要知道是哪個被按下,當然也可以幫按鈕加上 name 屬性來辨認。以下範例有十個按鈕,PHP 會判斷是誰被按下:
<html><head><style>body, select{font-size:30px}</style></head> <body bgcolor="#ccccff"> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="post"> <?php for( $i = 1 ; $i <= 10 ; $i++ ){ echo "<input type=\"submit\" name=\"$i\" value=\"第 $i 號按鈕\">"; } ?> </form> <?php for( $i = 1 ; $i <= 10 ; $i++ ){ echo "按鈕 $i 是否被按下: " . (isset($_POST[$i]) ? "是" : "否" ) . "<br>"; } ?> </body></html>
若要與選單互動,則需在名稱後面加上「[]」,以代表形成陣列(各位可以自行測試看看不加「[]」的效果)。以下範例是將多選選單選到的數字相加,此範例中,由於沒有在 option 標籤中加入 value 屬性,所以 PHP 會取得 option 標籤夾住的內容;如果你為 option 標籤加上了 value 屬性,則 PHP 就會拿到 value 屬性的值:
<html><head><style>body, select{font-size:50px}</style></head> <body bgcolor="#ccccff"> <?php if( isset($_POST['number']) && gettype($_POST['number']) == 'array' ){ $sum = 0; foreach( $_POST['number'] as $i ){ $sum += (int)$i; } echo $sum; } ?> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="post"> <select name="number[]" multiple> <?php for( $i = 1 ; $i <= 10 ; $i++ ){ echo "<option>".$i."</option>"; } ?> </select> <input type="submit"> </form> </body></html>
而與多選方塊互動,也需要加上「[]」。此範例一樣是將選到的數字相加,只是介面不太一樣:
<html><head><style>body, select{font-size:50px}</style></head> <body bgcolor="#ccccff"> <?php if(isset($_POST['number']) && gettype($_POST['number']) == 'array'){ $sum = 0; foreach($_POST['number'] as $i){ $sum += (int)$i; } echo $sum; } ?> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="post"> <?php for($i=1;$i<=10;$i++){ echo "<input type=\"checkbox\" name=\"number[]\" id=\"$i\" value=\"$i\">"; echo "<label for=\"$i\">$i</label> "; } ?> <input type="submit"> </form> </body></html>
選單的一個常用的使用方式,就是選擇查看那些資料。以下範例為查看修課同學的資料,並假設 0~4 的課程中,你只有修其中 1~3 的那三門課(實際上的系統,會從資料庫中撈取資料出來顯示,但此處尚未介紹到相關方式,因此寫死在程式碼中):
<html><head><style>body, select{font-size:50px}</style></head> <body bgcolor="#ccccff"> <?php $classmates = array( '0' => array('Alien', 'Bob'), '1' => array('Cindy', 'David'), '2' => array('Ellen', 'Fox'), '3' => array('Grace', 'Henry'), '4' => array('Izero', 'Jack'), ); if( isset($_POST['course']) && gettype($_POST['course']) == 'array' ){ echo (int)$_POST['course'][0] . ': ' . join(', ', $classmates[$_POST['course'][0]]); } ?> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="post"> 請選擇課程: <select name="course[]"> <option value="1">流行音樂與數位創意運用</option> <option value="2">資料庫應用</option> <option value="3">WEB 程式設計</option> </select> <input type="submit"> </form> </body></html>
不過在上述的範例中,如果你會以透過開發者工具等方式來修改或送出假資料的話,是可以在選單未列出的情況下,看到另外兩門課的修課同學資料的。因此,比較完整的做法,必須是加上適當的檢查,如下:
<html><head><style>body, select{font-size:50px}</style></head> <body bgcolor="#ccccff"> <?php $classmates = array( '0' => array('Alien', 'Bob'), '1' => array('Cindy', 'David'), '2' => array('Ellen', 'Fox'), '3' => array('Grace', 'Henry'), '4' => array('Izero', 'Jack'), ); $courseTaken = array( '1' => '流行音樂與數位創意運用', '2' => '資料庫應用', '3' => 'WEB 程式設計' ); if( isset($_POST['course']) && gettype($_POST['course']) == 'array' ){ if(array_key_exists($_POST['course'][0], $courseTaken)){ echo (int)$_POST['course'][0] . ': ' . join(', ', $classmates[$_POST['course'][0]]); } else { echo '錯誤:你沒有修讀此門課程'; } } ?> <form action="<?php echo basename($_SERVER['PHP_SELF']);?>" method="post"> 請選擇課程: <select name="course[]"> <?php foreach( $courseTaken as $key => $val ){ echo '<option value="' . $key . '">' . $val . '</option>'; } ?> </select> <input type="submit"> </form> </body></html>
既然可以修改表單,那麼憑空創造一個表單也不是什麼大問題。在以下的範例中,雖然沒有表單(為了展示方便,故隱藏在註解之中),但我們仍然可以自己創造一個來送出資料。此範例的防禦狀況,通常會應用於只有特殊權限才可以送出資料,因此請參考 session 的篇章來進行防禦。
<html><head></head> <body bgcolor="#ccccff"> <?php if( isset($_POST['a']) && isset($_POST['b']) ){ echo (int)$_POST['a'] + (int)$_POST['b']; } ?> <!--form action="???.php" method="post"> <input type="text" name="a"> + <input type="text" name="b"> <input type="submit"> </form--> </body></html>