Form
Form with PHP
2019/09/23 (更新內容)
2023/10/08 (將作業改為應用範例)
PHP的輸入
介紹PHP的時候,大家一定很納悶,怎麼沒有提到輸入? 原因是,PHP本來就是為了web,所以,輸入就是要搭配html form了。
這是一個html form,當按鈕被按下時,因為method為post,所以,會以http post的方式呼叫action所指定的程式(welcome.php)。
Input / Text
welcome.html (詳參: PHP 7 Form Handling)
<html>
<body>
<form action="welcome.php" method="post">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>
</body>
</html>
$_POST
php利用$_POST來處理form送過來的資料。
welcome.php
<html>
<body>
Welcome <?php echo $_POST["name"]; ?><br>
Your email address is: <?php echo $_POST["email"]; ?>
</body>
</html>
$_GET
PHP Global Variables - Superglobals / $_GET
在URI後面還可以接一個查詢 (query),並以「?」隔開,如:「http://www.fju.edu.tw/sitemap.jsp?choice=0」,這個網頁利用查詢來決定不同角色看到的網站地圖,如:「http://www.fju.edu.tw/sitemap.jsp?choice=1」、「http://www.fju.edu.tw/sitemap.jsp?choice=2」。
例如:利用url傳遞變數subject
test_get.php?subject=PHP
如果查詢需要兩個以上的變數,可以使用「&」隔開,如:「http://www.fju.edu.tw/focusDetail.jsp?focusID=713&focusClassID=1」。
例如:傳遞兩個變數subject及web
test_get.php?subject=PHP&web=W3schools.com
test_get.html
<html>
<body>
<a href="test_get.php?subject=PHP&web=W3schools.com">Test $GET</a>
</body>
</html>
test_get.php
<html>
<body>
<?php
echo "Study " . $_GET['subject'] . " at " . $_GET['web'];
?>
</body>
</html>
應用範例
試試看怎麼寫一個陽春的登入系統
上週利用javascript進行驗證,那樣的驗證其實是不好的,因為使用者是可以看到javascript的內容,就可以看到帳號及密碼,所以,安全作法是由後端php程式檢查,我們來試著利用php檢查,當帳號輸入root、密碼輸入password,就顯示登入成功,否則就顯示登入失敗。
login.php
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="login_process.php" method="post">
帳號: <input type="text" name="account"><br>
密碼: <input type="password" name="password"><br>
<input type="submit" value="登入">
</form>
</body>
</html>
login_process.php
if裡的條件會是?
<?php
if ( ) {
echo "登入成功";
}
else {
echo "登入失敗";
}
?>
跳轉頁面
如果帳號輸入root、密碼輸入password,就到一個只有登出按鈕的畫面,按登出就回到登入畫面,帳號密碼錯誤也會回到登入畫面。
<?php
//檢查是否取得POST內容
$account = $_POST['account'] ?? ["N/A"];
$password = $_POST['password'] ?? ["N/A"];
if ($account==="root" && $password==="password" ) {
header("Location: success.php");
}
else {
header("Location: login.php");
}
?>
success.php
<html>
<body>
<h1>成功登入</h1>
</body>
</html>
如果帳號密碼錯誤,要在login.php裡顯示錯誤訊息,要怎麼寫?
login_process.php
<?php
//檢查是否取得POST內容
$account = $_POST['account'] ?? ["N/A"];
$password = $_POST['password'] ?? ["N/A"];
if ($account==="root" && $password==="password" ) {
header("Location: success.php");
}
else {
header("Location: login.php?msg=Error");
}
?>
login.php
<?php
$msg = $_GET["msg"]??"";
?>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="login_process.php" method="post">
帳號: <input type="text" name="account"><br>
密碼: <input type="password" name="password"><br>
<input type="submit" value="登入">
<?=$msg?>
</form>
</body>
</html>
為了讓大家容易理解,目前我們的寫法都是將畫面呈現跟處理邏輯分成兩個檔案,這樣的寫法雖然邏輯比較清楚,但是,當我們的系統越長越大,檔案數量就會太多,所以,一般比較熟練的開發者都會將兩個部分結合在一起,但也因為放在一起,就必須考慮到第一次呼叫這頁面時$_POST是不存在的。很多初學者會忘了這件事,導致第一次登入就出現錯誤訊息。
login.php
<?php
$msg = $_GET["msg"]??"";
//檢查是否取得POST內容
if ($_POST){ //如果POST有內容,進行以下的登入檢查
if ($_POST['account']==="root" && $_POST['password']==="password" ) {
header("Location: success.php");
}
else {
header("Location: login.php?msg=Error");
}
}
?>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="login.php" method="post">
帳號: <input type="text" name="account"><br>
密碼: <input type="password" name="password"><br>
<input type="submit" value="登入">
<?=$msg?>
</form>
</body>
</html>
Input / Checkbox
當輸入時,要讓使用者可以有多重狀態時,可以將多個checkbox都命名為status[],這樣就會把選擇內容當作陣列傳給php。
<!DOCTYPE html>
<html>
<body>
<form action="status.php" method="post">
name:<input type="text" name="name" />
<input type="checkbox" name="status[]" value="faculty" checked="checked" /> Faculty
<input type="checkbox" name="status[]" value="student" /> Student<br/>
<input type="checkbox" name="dinner" value="dinner" checked="checked" /> Dinner needed
<input type="submit" value="Submit" />
</form>
</body>
</html>
當使用者選擇任何一個選項或兩個選項,勾選的內容就會儲存在status陣列,可以利用foreach去檢查使用勾選的項目,為了避免使用者未勾選任何項目,要在php裡檢查並且給個空值。
status.php
<?php
echo $_POST["name"],"<br/>";
echo "Status:<br/>";
//new syntax in php 7
$statuslist = $_POST["status"]?? ["N/A"];
foreach( $statuslist as $status ) {
echo "$status <br/>";
}
$dinner = $_POST["dinner"]?? "";
echo "$dinner <br/>";
?>
Array
如果我們會根據參加者的需求去計算費用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="conference_process.php" method="post">
name:<input type="text" name="name" /><br/>
<input type="checkbox" name="program[]" value="1" checked="checked" /> 上午場 ($150)
<input type="checkbox" name="program[]" value="2" /> 下午場 ($100) <br />
<input type="checkbox" name="program[]" value="3" checked="checked" /> 午餐 ($60)
<input type="submit" value="Submit" />
</form>
</body>
</html>
利用array
conference_process.php
<?php
$program_price = array(0, 150, 100, 60);
//new syntax in php 7
$programlist = $_POST["program"]?? [0];
$price = 0;
foreach( $programlist as $program ) {
$price += $program_price[$program];
}
echo $_POST["name"].",您要繳交".$price." 元 <br/>";
?>
同樣效果,但利用php的associative array
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="conference_process.php" method="post">
name:<input type="text" name="name" /><br/>
<input type="checkbox" name="program[]" value="am" checked="checked" /> 上午場 ($150)
<input type="checkbox" name="program[]" value="pm" /> 下午場 ($100) <br />
<input type="checkbox" name="program[]" value="lunch" checked="checked" /> 午餐 ($60)
<input type="submit" value="Submit" />
</form>
</body>
</html>
conference_process.php
<?php
$program_price = array( "am"=>150, "pm"=>100, "lunch"=>60, "N/A"=>0);
//new syntax in php 7
$programlist = $_POST["program"]?? ["N/A"];
$price = 0;
foreach( $programlist as $program ) {
$price += $program_price[$program];
}
echo $_POST["name"].",您要繳交".$price." 元 <br/>";
?>
應用範例
試試看怎麼寫一個陽春的登入系統,檢查帳號、密碼,利用陣列存三組帳號、密碼,如果正確,就顯示登入成功,否則就回到登入畫面。
利用陣列存三組密碼的做法,可以利用isset先檢查帳號是否在陣列中存在,如果存在,就檢查對應的密碼是否跟輸入的密碼一致。
login.php
<?php
$accountList = array( "student1"=>"1", "student2"=>"2", "student3"=>"3");
$msg = $_GET["msg"]??"";
//檢查是否取得POST內容
if ($_POST){ //如果POST有內容,進行以下的登入檢查
$account = $_POST["account"]??"";
$password = $_POST["password"]??"";
if (isset($accountList[$account]) && $password == $accountList[$account] ) {
header("Location: success.php");
}
else {
header("Location: login.php?msg=Error");
}
}
?>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="login.php" method="post">
帳號: <input type="text" name="account"><br>
密碼: <input type="password" name="password"><br>
<input type="submit" value="登入">
<?=$msg?>
</form>
</body>
</html>
加一個fee.php
登入成功後,就跳轉fee.php,並讓會員輸入以下的欄位,輸入之後計算應收費用。
會費: 繳交 ($2000)/不繳交($0) (radio)
活動: (可複選 checkbox)
一日資管營 (會員免費 / 非會員 $300)
迎新茶會 (會員免費 / 非會員 $150)
迎新宿營 (會員$3000 / 非會員 $5500)
可以利用多維陣列 (詳參: PHP Multidimensional Arrays)讓程式碼乾淨一點,第二年如果金額改變,也只要修改陣列內容就好了。
$program_price = array(
array(2000, 0, 0, 3000),
array(0, 300, 150, 5500)
);
取得資料的方式:
$price = $program_price[0][3];
fee.php
<html>
<body>
<form action="fee_process.php" method="post">
<div>
會費:
<input type="radio" name="membershipFee" value=0 /> 繳交
<input type="radio" name="membershipFee" value=1 /> 不繳交
</div>
<div>
活動:
<input type="checkbox" name="program[]" value=0 /> 一日資管營
<input type="checkbox" name="program[]" value=1 /> 迎新茶會
<input type="checkbox" name="program[]" value=2 /> 迎新宿營
</div>
<input type="submit" value="確定" />
</form>
</body>
</html>
fee_process.php
<?php
$program_price = array(
array(2000, 0, 0, 3000),
array(0, 300, 150, 5500)
);
$price = 0;
//檢查是否取得POST內容
if ($_POST){ //如果POST有內容,進行以下的登入檢查
$membershipFee = $_POST["membershipFee"]??1;
$programs = $_POST["program"]??[];
$price += $program_price[$membershipFee][0];
foreach ($programs as $program){
$price += $program_price[$membershipFee][$program+1];
}
}
?>
<html>
<body>
費用:<?=$price?>
<a href="fee.php"><button>重新計算</button></a>
</body>
</html>
如果把兩個部分整合在一起,會比較複雜,大家可以試試看,當然,也有好處。
如果要把費用顯示在form裡面,兩個部分整合在一起,就可以直接取得二維陣列的內容,如果分開,二維陣列就必須寫兩次~~
也可以改用Associative array