PHP Cookie
Cookie 是儲存在使用者瀏覽器中的小型文字資料,用於在多個頁面請求之間保存資訊。由於 HTTP 協定本身是無狀態的,Cookie 提供了一種方式讓伺服器「記住」使用者,常用於記住登入狀態、儲存偏好設定、追蹤購物車內容等。
設定 Cookie
使用 setcookie() 函數可以設定 Cookie。Cookie 會隨著 HTTP 回應標頭傳送給瀏覽器,因此必須在任何 HTML 輸出之前呼叫。
<?php
// 基本設定
setcookie('username', 'Alice');
// 設定過期時間(1 小時後)
setcookie('username', 'Alice', time() + 3600);
// 完整參數
setcookie(
'username', // 名稱
'Alice', // 值
time() + 86400, // 過期時間(1 天後)
'/', // 路徑
'example.com', // 網域
true, // 只在 HTTPS 傳送
true // HttpOnly(JavaScript 無法存取)
);
?>
setcookie() 必須在任何輸出之前呼叫。PHP 7.3+ 選項陣列
PHP 7.3 引入了更清晰的選項陣列語法,可以用具名參數取代多個位置參數,讓程式碼更易讀:
<?php
setcookie('username', 'Alice', [
'expires' => time() + 86400,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict' // Strict, Lax, 或 None
]);
?>
讀取 Cookie
瀏覽器會在後續請求中自動傳送 Cookie,PHP 會將收到的 Cookie 存入 $_COOKIE 超全域陣列中。注意:剛設定的 Cookie 要到下一次請求才能讀取,因為 Cookie 是隨回應傳送、隨請求接收的。
<?php
// 檢查 Cookie 是否存在
if (isset($_COOKIE['username'])) {
echo "Hello, " . $_COOKIE['username'];
}
// 使用 null 合併運算子
$username = $_COOKIE['username'] ?? 'Guest';
?>
刪除 Cookie
要刪除 Cookie,需要將其過期時間設為過去的時間點。這會讓瀏覽器認為 Cookie 已過期而將其移除:
<?php
// 將過期時間設為過去
setcookie('username', '', time() - 3600);
// 或設定空值
setcookie('username', '', [
'expires' => time() - 3600,
'path' => '/'
]);
?>
安全注意事項
<?php
// 1. 不要儲存敏感資料
// 錯誤
setcookie('password', 'secret123');
// 2. 使用 HttpOnly 防止 XSS
setcookie('session', $value, ['httponly' => true]);
// 3. 使用 Secure 只在 HTTPS 傳送
setcookie('session', $value, ['secure' => true]);
// 4. 使用 SameSite 防止 CSRF
setcookie('session', $value, ['samesite' => 'Strict']);
// 5. 驗證 Cookie 值
$userId = $_COOKIE['user_id'] ?? null;
if ($userId !== null) {
$userId = filter_var($userId, FILTER_VALIDATE_INT);
if ($userId === false) {
// 無效的值
}
}
?>
實際範例
記住我功能
<?php
// 登入時
if ($rememberMe) {
$token = bin2hex(random_bytes(32));
// 儲存 token 到資料庫
saveRememberToken($userId, $token);
setcookie('remember_token', $token, [
'expires' => time() + 30 * 24 * 60 * 60, // 30 天
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]);
}
// 檢查自動登入
if (!isLoggedIn() && isset($_COOKIE['remember_token'])) {
$user = findUserByRememberToken($_COOKIE['remember_token']);
if ($user) {
login($user);
}
}
?>
偏好設定
<?php
// 儲存偏好
$preferences = json_encode(['theme' => 'dark', 'lang' => 'zh-TW']);
setcookie('preferences', $preferences, time() + 365 * 24 * 60 * 60);
// 讀取偏好
$prefs = json_decode($_COOKIE['preferences'] ?? '{}', true);
$theme = $prefs['theme'] ?? 'light';
?>