Session 過期受兩個設定控制:
session.cookie_lifetime(預設 0,瀏覽器關閉失效)。session.gc_maxlifetime(預設 1440 秒 = 24 分鐘),垃圾回收(GC)機制定期清理超過此秒數的 Session 檔案。
修改後需重啟 PHP-FPM/Apache 生效。
實作 SessionHandlerInterface,將 Session 存入資料庫/Redis,自行管理過期邏輯,避開檔案系統 GC 不確定性。
pdo = $pdo; } public function open($savePath, $sessionName): bool { return true; } public function close(): bool { return true; } public function read($id): string|false { $stmt = $this->pdo->prepare('SELECT data FROM sessions WHERE id = ? AND expiry > ?'); $stmt->execute([$id, time()]); return $stmt->fetchColumn() ?: ''; } public function write($id, $data): bool { $expiry = time() + ini_get('session.gc_maxlifetime'); $stmt = $this->pdo->prepare(' INSERT INTO sessions (id, data, expiry) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE data = VALUES(data), expiry = VALUES(expiry) '); return $stmt->execute([$id, $data, $expiry]); } public function destroy($id): bool { $stmt = $this->pdo->prepare('DELETE FROM sessions WHERE id = ?'); return $stmt->execute([$id]); } public function gc($maxlifetime): int|false { $stmt = $this->pdo->prepare('DELETE FROM sessions WHERE expiry < ?'); $stmt->execute([time()]); return $stmt->rowCount(); } } // 註冊 $handler = new DbSessionHandler($pdo); session_set_save_handler($handler, true); session_start();
| 誤區 | 正確認知 |
|---|---|
| 只設定 cookie_lifetime 很大 | 伺服端 gc_maxlifetime 到期仍會刪除資料,導致 Cookie 存在但 Session 失效 |
| 以為 GC 每次請求都執行 | GC 機率由 session.gc_probability / session.gc_divisor 決定(預設 1/1000) |
| 共享主機無法改 php.ini | 用 .user.ini 或運行時 ini_set,或改用資料庫 Session |
Session 過期需雙端同步設定:客戶端 Cookie 存活(cookie_lifetime)與伺服端資料存活(gc_maxlifetime)。長效登入建議改用資料庫/Redis 自訂處理器,獲得精確可控的過期管理。