PHP 表單、狀態管理與檔案處理

PHP 網站程式設計與資料庫基礎班 DAY 5

講師:張凱迪(KD.Chang)

Copyright © 2014 All rights reserved

Outline

PHP 狀態管理

表單處理

檔案處理

寄送電子郵件

PHP 狀態管理

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 預定變數

<?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);
?>

HTTP 標頭

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 狀態管理基礎

當 PHP 程式在伺服器執行時,HTTP 通訊協定並不會保持連線並記錄使用者狀態,所以必須透過其他方法保留使用者狀態方便跨頁傳遞資訊,PHP 依儲存位置可以分為客戶端管理(存在使用者電腦或網頁)和伺服器端管理(存在伺服器)

 

1. 客戶端管理

表單欄位

URL 網址參數

Cookies

 

2. 伺服器端管理

Session 

文字檔案

資料庫

XML 文件

PHP 狀態管理基礎

Cookies 基礎

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

Cookies 處理

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);
?>

Session 基礎

相對於 Cookie 於客戶端,Session 是一種於伺服器端進行狀態管理的機制,伺服器透過 Session 變數(伺服器用檔案存)可以識別使用者 id 是否為同一個(記錄使用者狀態),並讓使用者在進到網站到結束瀏覽器的期間的資料可以跨多個 PHP 程式傳遞

Session 處理

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

 

表單處理

表單處理與 URL 參數

表單傳送時可以使用 GET 或是 POST 方法,在伺服器端可以使用 $_GET、$_POST 預設全域結合陣列取得欄位值 (Live Coding) 

 

參考範例

簡易表單欄位驗證

良好的表單驗證可以避免使用者輸入非正確的資料。一般來說可以透過前端的 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 提供檔案讀寫的函數方便開發者讀寫檔案(一般分為文字檔和二進位檔案,網頁程式設計主要處理文字檔,請注意讀寫權限)

 

檔案讀寫

<?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 為後端接受檔案的程式位置

enctype

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 '上傳失敗';
	}
}
?>

練習五

請利用檔案上傳方法上傳圖片,並顯示在網頁上

練習六

請運用檔案處理機制,製作簡單留言板

寄送電子郵件

寄送電子郵件函數

PHP 提供 mail() 函數透過 SMTP 伺服器寄送電子郵件,但目前必須注意擋信等問題,也有許多網路服務提供電子郵件的寄送服務:MailChimpSendGrid電子豹

 

PHP 是在 php.ini (config 資料夾中) 設定電子郵件 SMTP 伺服器資訊:

1. SMTP 伺服器網域名稱或是 IP 位置,一般預設 localhost

2. smtp_port SMTP 伺服器 port,一般預設 25 

3. sendmail_from 寄件者電子郵件

寄送電子郵件函數

<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 函數寄一封信到自己的電子信箱!

Q & A

PHP 表單、狀態管理與檔案處理

By 張凱迪(KD Chang)

PHP 表單、狀態管理與檔案處理

本課程分為 前端網頁程式設計基礎班 和 PHP 網站程式設計與資料庫基礎班 兩個班,希望藉由這次課程能讓對於網頁程式設計有興趣的同學可以有一個入門的管道,在上完課程後可以有足夠的自學能力能夠持續學習進修,進而將自己的點子付諸實踐。課程網站:http://kdchang.cc/web-programming-course/ Email:web.programming.course@gmail.com FB 粉絲專頁:https://fb.com/Web.Programming.Course

  • 2,454