Module 1 - 網路應用程式四大元件
探討網頁架構、伺服器機制及前端與伺服器端的運作對比
四大元件運作原理
費曼簡化比喻:網頁應用的「餐廳理論」
把整個網頁架構想成去餐廳吃飯:
1. Web Browser (瀏覽器/客戶端):就是「點餐的客人」,發送請求並享用最後上桌的菜餚。
2. Web Server (網頁伺服器,如 Apache):就是「服務生」,負責接收訂單、傳遞需求並送菜。
3. Database Server (資料庫,如 MySQL):就是「儲藏室」,存放著所有新鮮的食材原料。
4. Server-side Language (後端語言,如 PHP):就是後廚的「主廚」,根據訂單從儲藏室撈食材,加工煮成佳餚(HTML),再交給服務生端給客人。
- Client-Side 職責: 擅長驗證使用者輸入、響應瀏覽器端的即時事件(如 JavaScript 彈出視窗),完全不涉及伺服器硬碟。
- Server-Side 職責: 擅長存取伺服器上的資料庫進行安全讀寫,控制不同狀態(如登入/管理員權限)下的動態網頁生成。
歷屆常見考點與考題陷阱
常見致命錯誤觀念
陷阱: 考試常問「客戶端程式碼(JavaScript)可以直接安全地讀寫伺服器上的 MySQL 資料庫嗎?」
正解: 絕對不行!客戶端程式執行在客人的瀏覽器中,根本無法也不應擁有伺服器資料庫的連線權限。必須透過伺服器端的 PHP 發送 SQL 查詢才可以讀寫資料庫。
核心滿分知識點摘要
- Apache 特性: 開源 HTTP 伺服器,多工作業,硬體資源消耗低、快速且具備高可擴展性。預設文件根目錄(Document Root)常為
htdocs或www。 - MySQL 特性: 高效能關聯式資料庫管理系統(RDBMS),支援多使用者並符合 SQL 標準。
PHP 解析生命週期
費曼邏輯推演:PHP 程式碼的生命週期
當瀏覽器請求一個 .php 文件時,伺服器不是直接把代碼送回去,而是經歷四步:
1. 請求: 瀏覽器發送 `.php` 網頁文件請求。
2. 轉交: Web Server(Apache)收到後發現副檔名是 `.php`,立刻轉交給 PHP 解析器 (PHP Parser)。
3. 執行: Parser 執行 PHP 標籤 <?php ... ?> 內的所有邏輯與運算。
4. 回傳: Parser 把執行結果轉化為**純 HTML/CSS** 文字,交還給 Apache 傳回瀏覽器渲染。所以客人在瀏覽器「檢視原始碼」時,絕對看不見任何一行 PHP 代碼!
考題趨勢與輸出差異
核心考點:echo 與 print() 的本質區別
考試極常考填空或選擇兩者的差異:
1. echo: 輸出一個或多個字串,速度較快,且**沒有任何回傳值**。
2. print(): 輸出字串,類似 JavaScript 的 document.write(),但它是一個函式,**成功執行時會固定回傳 1**,因此可以用在更複雜的條件表達式中。
基礎語法滿分模板
// 標準宣告與變數解析
$course = "ITP4523M";
echo "單引號與雙引號的重大差異:<br>";
echo "雙引號會解析變數:This is $course<br>"; // 輸出: This is ITP4523M
echo '單引號不解析變數:This is $course<br>'; // 輸出: This is $course
?>
表單資料動態防呆驗證
在實務網頁開發或期末大題中,驗證使用者傳來的表單數據(漏填、未選取)是核心安全關卡。利用關聯式陣列對所有輸入欄位進行遍歷與防呆,是最乾淨且不容易出錯的架構。
考題趨勢:文字框與單選框的驗證陷阱
考點陷阱:strlen() 與 isset() 的適配對象
1. **文字框 (Text / Textarea)**:即使用戶沒填,POST 傳過來的依然是個空字串 "",它的變數是**存在**的!所以不能用 isset() 檢查,必須使用 strlen($_POST['field']) > 0 或 empty()。
2. **單選框/核取框 (Radio / Checkbox)**:如果用戶完全沒點選,POST 陣列裡**根本不會有這個 key**!此時直接讀取會觸發 Undefined Index 錯誤,因此**必須使用 isset($_POST['radio_name'])** 進行檢查!
全欄位動態防呆遍歷滿分語法模板
// 滿分結構:定義表單所有欄位屬性與顯示文字
$fields = array(
'myname' => array('text', 'Name'),
'gYear' => array('text', 'Graduate Year'),
'isAlumni' => array('radio', 'Alumni')
);
$dataOK = true;
$errMsg = "";
foreach ($fields as $fieldname => $info) {
$type = $info[0];
$label = $info[1];
if ($type == 'text') {
if (strlen(trim($_POST[$fieldname])) == 0) {
$errMsg .= "$label 欄位不可空白!<br>";
$dataOK = false;
}
} else if ($type == 'radio') {
if (!isset($_POST[$fieldname])) {
$errMsg .= "請選取 $label 選項!<br>";
$dataOK = false;
}
}
}
?>
檔案上傳設定與 $_FILES 陣列
檔案上傳必須在 HTML 表單加上 enctype="multipart/form-data"。而在伺服器端,最大上傳限制受到 php.ini 的設定檔控制。我們可以利用 ini_get('post_max_size') 查詢本機目前的限制上限。
歷屆上傳大題核心必考點
5個核心檔案屬性與搬移函數
上傳檔案的資料會被存放在 $_FILES 二維陣列中,考試必考五大屬性填空:
1. $_FILES['file']['name']: 原始檔案名稱。
2. $_FILES['file']['type']: 檔案的 Mime Type (如 image/jpeg)。
3. $_FILES['file']['size']: 檔案大小 (以 Bytes 為單位)。
4. $_FILES['file']['tmp_name']: 檔案上傳後在伺服器端的**暫存路徑**。
5. $_FILES['file']['error']: 錯誤代碼 (0 代表成功)。
核心函數: 必須使用 move_uploaded_file(暫存路徑, 目標路徑) 將檔案從暫存區安全移至網頁資料夾中!
安全檔案上傳防呆處理模板
$target_folder = "upload/";
$target_file = $target_folder . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
// 1. 防重複檢查
if (file_exists($target_file)) {
echo "Sorry, file already exists.<br>";
$uploadOk = 0;
}
// 2. 限制檔案大小 (500KB 限額)
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "檔案太大!<br>";
$uploadOk = 0;
}
// 3. 執行安全搬移
if ($uploadOk == 1) {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "上傳成功!";
} else {
echo "搬移過程發生非預期錯誤。";
}
}
?>
資料庫連接與 CRUD 控制流程
網頁應用程式的核心在於處理動態資料。在 PHP 中,我們會使用 mysqli_connect 連接 MySQL,執行 SQL 指令(SELECT, INSERT, UPDATE, DELETE),並利用 mysqli_fetch_assoc() 撈取資料庫記錄為關聯式陣列。
考題趨勢:防重複與重導向控制
一頁式寫入流程控制重點
在實作新增記錄(INSERT)時,考卷常要求「防止資料重複寫入」以及「執行完畢後重定向」:
1. **防重複:** 先執行 SELECT 查詢該 ID 是否已存在。接著使用 mysqli_num_rows($rs) > 0 判斷,若大於 0 則代表重複,應立刻中斷流程。
2. **重定向跳轉:** 使用 header("location: 頁面.php?msg=訊息") 將網頁導回列表頁。注意:呼叫 header() 之前,網頁前方不能有任何的 HTML 或 echo 輸出!
防重複一頁式寫入滿分代碼模板
if (isset($_POST['tfID'])) {
require_once("conn.php");
// 步驟 1:防重複查詢
$check_sql = "SELECT * FROM Customers WHERE custID = '" . $_POST['tfID'] . "'";
$rs = mysqli_query($conn, $check_sql);
if (mysqli_num_rows($rs) > 0) {
// 已存在,跳轉並帶入錯誤訊息
header("location:" . $_SERVER['PHP_SELF'] . "?msg=" . urlencode("Record already exist!"));
} else {
// 步驟 2:安全寫入
$insert_sql = "INSERT INTO Customers (custID, custName) VALUES ('".$_POST['tfID']."', '".$_POST['tfName']."')";
mysqli_query($conn, $insert_sql);
if (mysqli_affected_rows($conn) > 0) {
header("location:" . $_SERVER['PHP_SELF'] . "?msg=" . urlencode("Added successfully"));
}
}
}
?>
資料庫連接異常攔截
當資料庫伺服器宕機、密碼錯誤、或是 SQL 語法拼錯時,程式如果沒有進行處理,會直接崩潰或暴露出敏感的伺服器資訊。搭配 or die() 可以在出錯的當下攔截並印出乾淨的偵錯內容。
考試常見填空函數對比
核心辨析:mysqli_connect_error() vs mysqli_error()
這兩個錯誤處理函數極容易在填空題中混淆:
1. mysqli_connect_error(): **不需要任何參數**。專門用在 mysqli_connect() 失敗時,抓取「資料庫連線失敗」的理由。
2. mysqli_error($conn): **必須傳入資料庫連線變數 `$conn`**。用在 mysqli_query() 失敗時,抓取「SQL 語法寫錯、資料表不存在」等查詢層面的錯誤訊息。
標準安全連接與偵錯範例
// 1. 連線層面錯誤處理 (不用放參數)
$conn = mysqli_connect("127.0.0.1", "root", "", "labdb") or die(mysqli_connect_error());
// 2. 查詢層面錯誤處理 (必須放 $conn 變數)
$sql = "SELECT * FROM invalid_table_name";
$rs = mysqli_query($conn, $sql) or die(mysqli_error($conn));
?>
狀態管理與無狀態協議
HTTP 是一個無狀態協議 (Stateless protocol)。這意味著瀏覽器上一次發送的請求與下一次發送的請求,在伺服器眼中是完全獨立、毫無關聯的(伺服器沒有記憶能力)。為了讓網頁記得使用者(例如保持登入狀態、購物車),必須使用狀態管理技術:Cookie 與 Session。
Cookie 與 Session 世紀大對比
費曼比喻:俱樂部置物櫃理論
1. Cookie (客戶端暫存):就像你把會員資料卡**放在自己口袋裡**。每次去俱樂部都掏出來給櫃檯看。因為在你自己口袋,你隨時可以把它丟掉,或者是別人也可能偷看,安全度較低。
2. Session (伺服器端儲存):就像你把貴重物品安全地**鎖在俱樂部的置物櫃中**。櫃檯只交給你一把「置物櫃鑰匙」(這把鑰匙就是 Session ID,會透過 Cookie 存在你的瀏覽器中)。每次你交出鑰匙,伺服器就去後台對應的櫃子拿資料。安全度極高!
| 比較維度 | Cookie | Session |
|---|---|---|
| 儲存位置 | 客戶端瀏覽器 (Client-side) | 網頁伺服器記憶體/檔案 (Server-side) |
| 生命週期 | 可自訂過期時間 (即便瀏覽器關閉依然存在) | 預設在**關閉瀏覽器**時即刻消失 |
| 安全性 | 較低 (容易遭篡改) | 極高 (使用者無法直接摸到真實資料) |
狀態宣告核心基礎
// 建立一個名字為 user, 值為 Stanley, 期限為 1 小時的 Cookie
setcookie("user", "Stanley", time() + 3600);
// 使用 Session 之前,必須在網頁最頂端呼叫啟動方法
session_start();
$_SESSION['role'] = "admin";
?>
會話生命週期管理與安全銷毀
管理 Session 的狀態包含:確認變數是否存在、更新內容(例如累加存取次數),以及在使用者點擊「登出」時,安全徹底地清除置物櫃裡所有的變數與包裏,確保帳號安全。
考題趨勢:三種銷毀 Session 函數辨析
核心語法填空:unset、session_unset 與 session_destroy
考試常在登出系統的大題中,要求填入正確的銷毀函數。它們的威力與範圍完全不同:
1. unset($_SESSION['key']);: 僅僅清除、釋放**單一個**會話變數(例如只拿掉購物車,但保留登入狀態)。
2. session_unset();: 清空當前 Session 箱子裡**所有的會話變數**,釋放所有記憶體,但箱子本身(Session ID 鑰匙)還在。
3. session_destroy();: 徹底**銷毀、瓦解整個 Session 會話**,把伺服器上的檔案徹底刪除,鑰匙直接作廢。
完整網頁存取計數器與登出銷毀模板
網頁累加計數器實作:
session_start();
if (!isset($_SESSION['access_count'])) {
$_SESSION['access_count'] = 1;
echo "這是您第一次造訪本網頁!";
} else {
$_SESSION['access_count'] += 1;
echo "您已經重新載入造訪了 " . $_SESSION['access_count'] . " 次!";
}
?>
標準安全登出銷毀流程:
session_start();
// 1. 清空所有變數值
session_unset();
// 2. 徹底銷毀會話箱子
session_destroy();
// 3. 跳轉回登入首頁
header("location: login.php");
?>
陣列操作與字串處理函數
精通 PHP 的內建函數能大幅提高程式碼撰寫效率。在考試卷中,最常與 Heredoc 字串大題或關聯陣列混合考核。
核心滿分函數考點記憶庫
- 陣列尾端自動追加: 使用空方括號語法
$array[] = "新元素";可以不需指定索引,自動將值推入陣列最後方。 - 移除特定索引項目: 使用
unset($serviceBookings['booking1']);可以將指定鍵值的項目從記憶體中完全移除。 - 字串長度與單字量計算:
strlen($str)用於計算字串的總字元長度;str_word_count($str)用於統計字串內含的英文單字個數。
陣列與字串綜合實戰代碼
// 1. 陣列追加與刪除
$petCategories = ["Dog", "Cat"];
$petCategories[] = "Fish"; // 動態追加
unset($petCategories[0]); // 移除 Dog
// 2. Heredoc 字串處理與函數計算
$campaign = <<<EOD
this is a biggest pet exhibition in HK
Come and join us to explore the wonderful world of pets!
EOD;
echo "字元長度:" . strlen($campaign) . "<br>"; // 輸出: 101
echo "單字個數:" . str_word_count($campaign); // 輸出: 19
?>
Advanced PHP - 物件導向程式設計 (OOP)
從 PHP 5 開始,系統全面支援物件導向開發樣式。我們可以宣告類別 (Class),將屬性變數與成員函式封裝在一起,並透過 new 關鍵字將其實例化為實體物件。
物件導向核心必考語法細節
語法細節:成員呼叫符號與構造函數
考試若考出 OOP 題型,有兩個地方是失分高發期:
1. **成員呼叫符號:** 在 JavaScript 中我們用點符號(`object.method()`),但在 PHP 中**必須使用瘦箭頭符號($object->method())**!
2. **建構子魔術方法:** 在類別內部宣告建構子(當物件被 new 出來時會立刻自動執行的初始化函式),其名稱必須嚴格固定寫為 **function __construct()**(前方是兩個連續的底線!)。
標準類別宣告與實例化模板
class Member {
var $uName;
// 建構子魔術方法 (雙底線)
function __construct($name) {
$this->uName = $name;
}
function showWelcome() {
echo "Welcome, " . $this->uName;
}
}
// 實例化物件並調用成員方法 (使用 -> 符號)
$user1 = new Member("Lai Tuk Sui");
$user1->showWelcome(); // 輸出: Welcome, Lai Tuk Sui
?>