在 PHP 開發中,Session 用於跨請求保持用戶狀態。隨著業務流轉,我們常需要:
對應的核心函數分別是 unset() 與 session_destroy(),但實際操作中常被誤用,導致「以為清除了其實沒清除」或「Session 文件殘留」等問題。
<?php // 必須先啟動 Session session_start(); // 刪除特定鍵 unset($_SESSION['views']); // 或刪除多個 unset($_SESSION['user_id'], $_SESSION['token']); // 驗證 var_dump(isset($_SESSION['views'])); // false ?>
關鍵點:
unset($_SESSION['key']) 僅從 $_SESSION 超全局變量中移除該鍵,不會刪除服務端 Session 存儲文件中的數據,下次請求 session_start() 時該鍵不會出現,但 Session ID 保持不變。$_SESSION = [] 重置整個陣列,但仍保留 Session ID。<?php
session_start();
// 1. 清空當前請求中的 $_SESSION 陣列
$_SESSION = [];
// 2. 刪除客戶端 Cookie 中的 Session ID(可選但推薦)
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// 3. 銷毀服務端 Session 數據文件
session_destroy();
// 之後不可再使用 $_SESSION,除非重新 session_start()
?>
標準三步曲解析:
$_SESSION = []:清空記憶體中的 Session 數據,防止後續代碼誤讀殘留值。session_destroy() 不會自動刪除客戶端 Cookie。若不刪除 Cookie,瀏覽器下次請求仍攜帶舊 Session ID,PHP 會嘗試讀取已刪除的存儲文件(產生新空 Session),導致邏輯混亂。session_destroy():真正刪除服務端存儲(文件、Redis、Memcached 等)中的 Session 數據。| 誤區 | 正確做法 |
|---|---|
只調用 session_destroy() 不清空 $_SESSION | 當前請求中 $_SESSION 仍可讀寫,建議先 $_SESSION = [] |
以為 session_destroy() 會刪除 Cookie | 必須手動 setcookie(session_name(), '', time()-3600, ...) |
銷毀後直接繼續用 $_SESSION | 銷毀後 $_SESSION 失效,需重新 session_start() 才能使用新 Session |
使用 unset($_SESSION) 而非 $_SESSION = [] | unset($_SESSION) 會銷毀超全局變量本身,導致後續無法註冊 Session 變量,應用 $_SESSION = [] |
若使用 Redis、Memcached 或資料庫作為 Session 存儲(session.save_handler),session_destroy() 會自動調用對應驅動的 destroy() 方法刪除遠端數據。但刪除客戶端 Cookie 的邏輯完全相同,不可省略。
<?php session_start(); // 防止 Session Fixation 攻擊:銷毀舊 Session 並生成新 ID session_regenerate_id(true); // true 參數刪除舊 Session 文件 // 然後執行上述標準三步曲銷毀新 Session(或直接保留新空 Session 作為登出後狀態) ?>
unset($_SESSION['key'])。$_SESSION = [] → 刪除 Cookie → session_destroy()。