2019/09/23 (更新內容)
2023/10/08 (將作業改為應用範例)
2024/09/12 (應用範例改為作業)
2024/09/17 (微調內容)
2024/09/26 (微調內容)
介紹PHP的時候,大家一定很納悶,怎麼沒有提到輸入? 原因是,PHP本來就是為了web,所以,輸入就是要搭配html form了。
這是一個html form,當按鈕被按下時,因為method為post,所以,會以http post的方式呼叫action所指定的程式(welcome.php)。
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>
php利用$_POST來處理form送過來的資料。
welcome.php
<html>
<body>
Welcome <?= $_POST["name"] ?><br>
Your email address is: <?= $_POST["email"] ?>
</body>
</html>
如果我們的form忘了method,在html裡的預設是get
<html>
<body>
<form action="welcome.php">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>
</body>
</html>
這時候會有兩個差別:
第一、網址會變成:
http://localhost/web/welcome.php?name=ben&email=jitsung.wu%40gmail.com
因為HTTP Get會將form的內容以查詢(query)的方式傳遞,也就是在URI後面還可以接一個查詢,並以「?」起頭,不同變數之間以「&」隔開。
第二、會產生錯誤訊息:
Welcome
Warning: Undefined array key "name" in C:\xampp\htdocs\web\welcome.php on line 4
Your email address is:
Warning: Undefined array key "email" in C:\xampp\htdocs\web\welcome.php on line 5
PHP Global Variables - Superglobals / $_GET
這時候,php程式就要改成:
<html>
<body>
Welcome <?= $_GET["name"] ?><br>
Your email address is: <?= $_GET["email"] ?>
</body>
</html>
一般而言,form都會使用post,例如,我們利用form進行登入,我們不想把帳號密碼顯示在網址中。
那甚麼時候會用到get query呢?
例如,校首頁利用查詢看到不同的內容,如:「https://www.fju.edu.tw/sitemap.jsp?choice=0」、「https://www.fju.edu.tw/sitemap.jsp?choice=1」、「https://www.fju.edu.tw/sitemap.jsp?choice=2」。
如果查詢需要兩個以上的變數,可以使用「&」隔開,如:「https://www.fju.edu.tw/focusDetail.jsp?focusID=713&focusClassID=1」。
試試看怎麼寫一個陽春的登入系統
上週利用javascript進行驗證,那樣的驗證其實是不好的,因為使用者是可以看到javascript的內容,就可以看到帳號及密碼,所以,安全作法是由後端php程式檢查,我們來試著利用php檢查,當帳號輸入root、密碼輸入password,就顯示登入成功,否則就顯示登入失敗。(60%)
套用bootstrap (40%)
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,就到一個只有登出按鈕的畫面,按登出就回到登入畫面,帳號密碼錯誤也會回到登入畫面。
跳轉頁面可使用header
header("Location: success.php");
<?php
//檢查是否取得POST內容
$account = $_POST['account'] ?? ["N/A"];
$password = $_POST['password'] ?? ["N/A"];
if ( ) {
//跳轉到success.php
}
else {
//跳轉到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 ( ) {
//跳轉到success.php
}
else {
//跳轉到login.php並傳遞msg變數
}
?>
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>
Form Controls (getbootstrap.com)
Forms (w3school)
<?php
$msg = $_GET["msg"]??"";
?>
<html>
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<div class="container">
<form action="login_process.php" method="post">
<input placeholder="帳號" class="form-control" type="text" name="account"><br>
<input placeholder="密碼" class="form-control" type="password" name="password"><br>
<input class="btn btn-primary" type="submit" value="登入">
<?=$msg?>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>
為了讓大家容易理解,目前我們的寫法都是將畫面呈現跟處理邏輯分成兩個檔案,這樣的寫法雖然邏輯比較清楚,但是,當我們的系統越長越大,檔案數量就會太多,所以,一般比較熟練的開發者都會將兩個部分結合在一起,但也因為放在一起,就必須考慮到第一次呼叫這頁面時$_POST是不存在的。很多初學者會忘了這件事,導致第一次登入就出現錯誤訊息。
login.php
<?php
$msg = $_GET["msg"]??"";
//檢查是否取得POST內容
if ($_POST){ //如果POST有內容,進行以下的登入檢查
if ( ) {
//跳轉到success.php
}
else {
//跳轉到login.php並傳遞msg變數
}
}
?>
<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>
本週作業到此為止
當輸入時,要讓使用者可以有多重狀態時,可以將多個checkbox都命名為status[],這樣就會把選擇內容當作陣列傳給php。
status.html
<!DOCTYPE html>
<html>
<body>
<form action="status.php" method="post">
name:<input type="text" name="name" /><br/>
<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/>";
?>
這樣寫會有個問題,如果直接執行status.php,會得到:
Warning: Undefined array key "name" in C:\xampp\htdocs\web\status.php on line 2
Status:
N/A
要避免這樣的問題,一種做法就是跟上週一樣把兩個程式合併,另一種做法就是將status.php改為:
<?php
if ($_POST){
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/>";
}
else {
header("Location: status.html");
}
?>
如果我們會根據參加者的需求去計算費用
conference.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="conference.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>
conference.php
<?php
if ($_POST){
$program_price = array(0, 150, 100, 60);
$name = $_POST["name"]??"N/A";
//new syntax in php 7
$programlist = $_POST["program"]?? [0];
$price = 0;
foreach( $programlist as $program ) {
$price += $program_price[$program];
}
echo "$name ,您要繳交 $price 元 <br/>";
}
else {
header("Location: conference.html");
}
?>
慢慢的,內容越來越多了~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<div class="container">
<form action="conference.php" method="post">
<div class="row">
<div class="col-6">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="_name" name="name" placeholder="您的姓名" required>
<label for="_name">Name</label>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" name="program[]" id="program_1" checked="checked">
<label class="form-check-label" for="program_1">
上午場 ($150)
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="2" name="program[]" id="program_2">
<label class="form-check-label" for="program_2">
下午場 ($100)
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="3" name="program[]" id="program_3" checked="checked">
<label class="form-check-label" for="program_3">
午餐 ($60)
</label>
</div>
</div>
</div>
<input class="btn btn-primary" type="submit" value="Submit" />
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>
conference.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="conference.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.php
<?php
if ($_POST){
$program_price = array( "am"=>150, "pm"=>100, "lunch"=>60, "N/A"=>0);
//new syntax in php 7
$programlist = $_POST["program"]?? ["N/A"];
$name = $_POST["name"]??"N/A";
$price = 0;
foreach( $programlist as $program ) {
$price += $program_price[$program];
}
echo "$name ,您要繳交 $price 元 <br/>";
}
else {
header("Location: conference.html");
}
?>
試試看怎麼寫一個陽春的登入系統,檢查帳號、密碼,利用陣列存三組帳號、密碼,如果正確,就跳轉到fee.html,否則就回到登入畫面。
利用陣列存三組密碼的做法,可以利用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 ( ) {
//跳轉到fee.html
}
else {
//跳轉到login.php並傳遞msg變數
}
}
?>
<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.html
更改login.php,登入成功後,就跳轉fee.html,並讓會員輸入以下的欄位。
fee.html
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form action="fee.php" method="post">
<div>
會費:
<input type="radio" name="membershipFee" value=1 /> 繳交
<input type="radio" name="membershipFee" value=0 /> 不繳交
</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>
輸入之後計算應收費用。
會費: 繳交 ($2000)/不繳交($0) (radio)
活動: (可複選 checkbox)
一日資管營 (會員免費 / 非會員 $300)
迎新茶會 (會員免費 / 非會員 $150)
迎新宿營 (會員$3000 / 非會員 $5500)
可以利用多維陣列 (詳參: PHP Multidimensional Arrays)讓程式碼乾淨一點,第二年如果金額改變,也只要修改陣列內容就好了。
$program_price = array(
array(300, 150, 5500),//非會員
array(0, 0, 3000) //會員
);
取得非會員、參加迎新宿營價格的方式:
$price += $program_price[0][2];
fee.php
<?php
$membershipFee=2000;
$program_price = array(
array(300, 150, 5500),//非會員
array(0, 0, 3000) //會員
);
$price = 0;
//檢查是否取得POST內容
if ($_POST){ //如果POST有內容,進行以下的登入檢查
$membership = $_POST["membershipFee"]??1;
$programs = $_POST["program"]??[];
//計算費用
}
?>
<html>
<body>
費用:<?=$price?>
<a href="fee.html"><button>重新計算</button></a>
</body>
</html>
請完成fee.php
參考上週的login.php,修改本週的login.php,參考conference.html修改fee.html及fee.php,試著套用形形色色的bootstrap元件。
getbootstrap.com
Forms (w3school)