講師:張凱迪(KD.Chang)
Copyright © 2014 All rights reserved
PHP 狀態管理
表單處理
檔案處理
寄送電子郵件
PHP 提供了預定變數(Predefined Variables)給開發者使用,方便開發者可以存取伺服器、Session、Cookie、表單、環境等資訊,預定變數為自動全域變數,預設為全域:
1. $GLOBALS 含所有全域變數,鍵值為所有全域變數名稱
2. $_SERVER 執行伺服器相關環境資訊
3. $_GET / $_POST 儲存 HTTP GET 和 POST 所傳送資訊
4. $_COOKIE 儲存 HTTP 傳遞 Cookie 資料的結合陣列
5. $_FILES 使用 HTTP POST 上傳檔案的資訊
6. $_ENV 儲存 PHP 執行環境變數的資訊
7. $_REQUEST 儲存 $_GET / $_POST / $_COOKIE 變數內容
8. $_SESSION 儲存 PHP 程式中 Session 變數的結合陣列
<?php
echo '$GLOBALS: ';
print_r($GLOBALS);
echo '<br>$_SERVER: ';
print_r($_SERVER);
echo '<br>$_GET: ';
print_r($_GET);
echo '<br>$_POST: ';
print_r($_POST);
echo '<br>$_COOKIE: ';
print_r($_COOKIE);
echo '<br>$_FILES: ';
print_r($_FILES);
echo '<br>$_ENV: ';
print_r($_ENV);
echo '<br>$_REQUEST: ';
print_r($_REQUEST);
echo '<br>$_SESSION: ';
print_r($_SESSION);
?>
PHP 程式可以透過送出 HTTP 標頭資訊來轉址或是定時更新網頁、指定文件內容和保留期限
<?php
// 常用,網址轉址
header("Location:http://www.google.com");
exit();
// 重新整理
header("Refresh: 2");
// 定義輸出 MIME 資料類型:
header("Content-type: text/html");
// 指定網頁在客戶端快取保留時間
header("Expires:" . '31, Dec 2014 00:00:00');
?>
PHP 輸出緩衝區(Output Buffer) 是用來儲存 PHP 程式輸出結果。與一般直接輸出在瀏覽器不同,將結果輸出到緩衝去將會等執行完 PHP 程式後再一次送到瀏覽器顯示。由於 header() 和 setcookie() 會更改 HTTP 標頭資訊,避免產生重複寫入標頭資訊的錯誤(如果關閉輸出緩衝區就會出錯)
在 PHP 中可以透過在 php.ini 中設定 output_buffering 屬性為 On,或是使用 PHP 函數自行輸出緩衝區
<?php
ob_start();
for($i = 0; $i < 10; $i++) {
echo $i; // 輸出字串的一個字
if(($i % 2) == 0) {
ob_flush(); // 輸出緩衝區
} else {
ob_clean(); // 清除緩衝區
}
}
ob_end_flush();
?>
當 PHP 程式在伺服器執行時,HTTP 通訊協定並不會保持連線並記錄使用者狀態,所以必須透過其他方法保留使用者狀態方便跨頁傳遞資訊,PHP 依儲存位置可以分為客戶端管理(存在使用者電腦或網頁)和伺服器端管理(存在伺服器)
1. 客戶端管理
表單欄位
URL 網址參數
Cookies
2. 伺服器端管理
Session
文字檔案
資料庫
XML 文件
Cookie 是一種記錄使用者資訊、偏好、購物車商品資訊和網站資訊等的小檔案,儲存位置是在使用者的瀏覽器
1. name : 屬性對應 Cookie 名稱,方便新增刪除
2. expires : 屬性指定 Cookie 有效期間
3. domain : 屬性,伺服器的網域名稱,預設建立 Cookie 伺服器網域名稱
4. path : domain 屬性下的路徑名稱,分辨建立者
5. secure : 需要在保密情況下才能在伺服器和客戶端傳送
Set-Cookie: name=value;expires=date;path=pname;domain=dname;secure
PHP 提供函數給開發者可以新增、刪除 Cookie。讀取 Cookie 則使用全域預定變數 $_COOKIE
<?php
$cookie_value = "餅乾真好吃^^"
$expire_time = strtotime("+10 days", time());
// 新增 Cookie
setcookie("my_cookie", $cookie_value, $expire_time);
// 讀取 Cookie
$item = $_COOKIE['my_cookie'];
echo $item;
// 刪除 Cookie(目前 timestamp - 10 Days => 馬上失效)
setcookie("my_cookie", "", time()-3600);
?>
相對於 Cookie 於客戶端,Session 是一種於伺服器端進行狀態管理的機制,伺服器透過 Session 變數(伺服器用檔案存)可以識別使用者 id 是否為同一個(記錄使用者狀態),並讓使用者在進到網站到結束瀏覽器的期間的資料可以跨多個 PHP 程式傳遞
PHP 提供函數給開發者可以操作 Session 變數。讀取 Session 則使用全域預定變數 $_SESSION
<?php
// 啟用交談期(Session),把這個 PHP 加入 Session
session_start();
// 給定 Session 值,並判斷變數是否存在,存在則印出
$_SESSION['my_session'] = "我想吃餅乾";
if(isset($_SESSION["my_session"])) {
echo $_SESSION['my_session'];
}
// 回傳 Session ID
$session_id = session_id();
echo $session_id;
// 刪除參數的 Session 看是否存在
unset($_SESSION['my_session']);
// 關閉交談期和刪除所有 Session 變數
session_destroy();
?>
購物車為電子商務網站的重要元素,且可以使用多種方式實作。這個練習希望大家透過上課講授的狀態管理機制(Cookie, Session)製作簡單的購物車 (Live Coding)
Hint : 可以先描繪整個購物車系統架構
1. cata.php
2. shopping_cart.php
3. delete_cart.php
4. add_cart.php
良好的表單驗證可以避免使用者輸入非正確的資料。一般來說可以透過前端的 HTML 和 JavaScript 進行驗證,也可以透過後端的程式進行資料驗證,若想增進使用者體驗建議在前端就進行驗證
<input type="text" name="username" size="10">
<?php
if(isset($_GET['username']) && strlen($_GET['username']) < 10) {
}
?>
表單處理是動態網站十分重要的功能之一,請運用 $_POST、$_GET 等全域變數接收前端表單所傳的資料製作簡單的會員登入系統
<form action="member.php" method="post">
<fieldset>
<legend>會員登入系統</legend>
<label for="id">
<div>帳號:<input type="text" name="id" required></div>
</label>
<label for="pwd">
<div>密碼:<input type="password" name="pwd" required></div>
</label>
<input type="submit" value="送出">
<input type="reset" value="重設">
</fieldset>
</form>
PHP 提供檔案操作的相關函數,可以開發者在伺服器進行檔案複製、更名、刪除和檢查檔案是否存在(有些情況需要權限)
<?php
// 取得執行檔案名稱,去除附檔名 .php
$file = basename($_SERVER['PHP_SELF'], ".php");
echo $file;
// 取得檔案實際路徑
$path = realpath($file . ".php");
echo "實際路徑: $path<bt>";
$parts = pathinfo($path);
// 取得路徑陣列資料
echo "路徑" . $parts["dirname"] . "<br>";
echo "檔名" . $parts["basename"] . "<br>";
echo "附檔名" . $parts["extension"] . "<br>";
?>
<?php
// 判斷檔案是否存在
if(file_exists($file . ".php")) {
echo "$file 檔案存在";
} else {
echo "檔案不存在";
}
// 複製檔案
if(!copy($file. ".php", $file. ".html")) {
echo "複製失敗";
} else {
echo "複製成功!";
}
// 更改檔名
rename($file . ".html", "rename.txt");
// 刪除檔案
unlink($file . ".html");
?>
<?php
$file = "index.php";
echo $file . "<br>";
// 檔案類型
echo filetype($file);
// 最後存取時間
echo date("n/d/Y h:i:s", fileatime($file));
// 最後更改時間
echo date("n/d/Y h:i:s", filemtime($file));
echo '<br>';
// 檔案大小
echo filesize($file);
// 是否為資料夾
echo is_dir($file);
// 是否為檔案
echo is_file($file);
// 是否可以讀寫、是否為上傳檔案
echo is_readable($file);
echo is_writable($file);
echo is_uploaded_file($file);
?>
檔案是儲存在電腦或儲存裝置中的位元組資料集,PHP 提供檔案讀寫的函數方便開發者讀寫檔案(一般分為文字檔和二進位檔案,網頁程式設計主要處理文字檔,請注意讀寫權限)
參考文件:第六章、Linux 的檔案權限與目錄配置
<?php
// r 開啟唯讀檔案
// r+ 開啟讀寫檔案,檔案指標位在檔頭,寫入資料會覆寫存在檔案內容
// w 開啟寫入檔案,清除目前檔案的所有內容,檔案指標指向檔頭,如果檔案不存在即建立檔案
// w+ 開啟可讀可寫檔案,並清除目前檔案的所有內容,檔案指標指向檔頭,如果檔案不存在建立此檔案
// a 開啟寫入檔案,檔案指標是指向檔尾,所以是在檔尾寫入資料,如果檔案不存在,建立此檔案
// a+ 開啟讀寫檔案,檔案指標是指向檔尾,所以是在檔尾寫入資料,如果檔案不存在,建立此檔案
// b 開啟二進位檔案,例如圖片,需配合上述模式開啟"wb", "rb"
$file = 'index.php';
// 開啟檔案
$fp = fopen($file, 'r') or exit("檔案開啟錯誤");
// 關閉檔案
fclose($file);
?>
<?php
$file = "sample.txt";
$fp = fopen($file, "a");
$content = "hihi, php";
fputs($fp, $content, 10);
fwrite($fp, $content);
// fclose$file);
// // 讀取指定位元檔案內容
$contents = fread($fp, filesize($file));
// 讀取檔案,每一換行到陣列
$line = file($file);
// 輸出到緩衝區
$num = readfile($file);
?>
請利用寫入檔案函數將以下古詩寫入名為 poet.txt 的檔案中
人生不相見,動如參與商。
今夕复何夕,共此燈燭光。
少壯能幾時,鬢發各已蒼。
訪舊半為鬼,驚呼熱中腸。
焉知二十載,重上君子堂。
昔別君未婚,兒女忽成行。
怡然敬父執,問我來何方。
問答乃未已,驅兒羅酒漿。
夜雨剪春韭,新炊間黃粱。
主稱會面難,一舉累十觴。
十觴亦不醉,感子故意長。
明日隔山岳,世事兩茫茫。
請利用檔案函數,製作一個網站訪客記數器(Hint : 將人數寫入檔案,每次訪客造訪網站讀出檔案人數加 1 後寫回檔案)
檔案上傳是 PHP 程式中很重要的功能,處理檔案上傳主要有三個重點步驟:
1. 製作前端上傳頁面(HTML)表單
2. 接收處理上傳檔案(PHP),使用 $_POST 全域變數
3. 移動暫存上傳檔案到伺服器指定的資料夾
<form action="upload.php" mathod="post" enctype="multipart/form-data">
<label for="file">單檔案上傳</label>
<input type="file" name="file">
<hr>
<label for="file">多檔案上傳</label>
<input type="file" name="file[]">
<input type="file" name="file[]">
<input type="file" name="file[]">
</form>
製作前端上傳頁面有三個重點需要留意:
1. method 使用 psot
2. enctype 使用 multipart/form-data
3. action 為後端接受檔案的程式位置
from 中的 enctype 有三種屬性值
1. application/x-www-form-urlencoded
預設值,送出前會事先編碼,空白變成 + ,特殊字元轉 ASCII
2. multipart/form-data
使用於上傳檔案,不會事先編碼
3. text/plain
空白變成 + ,特殊字元不會轉 ASCII
PHP 可處理單一檔案上傳和多檔上傳,多檔上傳為陣列格式
<?php
echo "原始檔名: " . $_FILES['file']['name'] . '<br>';
echo "暫存檔名: " . $_FILES['file']['tmp_name'] . '<br>';
echo "檔案大小: " . $_FILES['file']['size'] . '<br>';
echo "檔案類型: " . $_FILES['file']['type'] . '<br>';
echo "錯誤編碼: " . $_FILES['file']['error'] . '<br>';
for ($i = 0; $i < (count($_FILES['file']) - 1);
$i++) {
echo "Name: " . $_FILES['file']['name'][$i] . '<br>';
echo "Temp: " . $_FILES['file']['tmp_name'][$i] . '<br>';
echo "Size: " . $_FILES['file']['size'][$i] . '<br>';
echo "Type: " . $_FILES['file']['type'][$i] . '<br>';
echo "Error: " . $_FILES['file']['error'][$i] . '<br>';
}
?>
PHP 檔案上傳後會先放到一個暫存資料夾(tmp),必須再用 move_uploaded_file 將檔案移動到你的網站資料夾中,所以須建立好一個放檔案的資料夾在網站目錄,並記得權限要設為可以寫入
<?php
$target_path = "uploads/";
$target_path = $target_path . basename($_FILES['file']['name']);
if ($_FILES["file"]["error"] > 0) {
echo '檔案錯誤';
} else {
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$upload_img = move_uploaded_file($_FILES['file']['tmp_name'], $target_path);
if ($upload_img) {
echo '上傳成功';
} else {
echo '上傳失敗';
}
}
?>
請利用檔案上傳方法上傳圖片,並顯示在網頁上
請運用檔案處理機制,製作簡單留言板
<form action="mail.php" method="post">
<div>收件者 : <input type="text" name="to"></div>
<div>寄件者 : <input type="text" name="from"></div>
<div>主旨 : <input type="text" name="subject"></div>
<br>
<div>郵件內容 : </div>
<textarea name="" id="" cols="30" rows="10" name="content"></textarea>
<div><input type="submit" name="mail" value="送出郵件"></div>
</form>
前端寄送郵件介面
<?php
if (isset($_POST['mail'])) {
$to = $_POST['to'];
$from = $_POST['from'];
$subject = $_POST['subject'];
$content = $_POST['content'];
$header = "From: $from \nReply-To: $from \n";
if (mail($to, $subject, $content, $header)) {
echo "飛鴿傳書成功!";
} else {
echo "嘿美受傷了Q";
}
}
?>
後端郵件發送
請使用 mail 函數寄一封信到自己的電子信箱!