首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP Session 機制深度剖析:Files vs User 兩種 Handler 的儲存流程與自定義實現

     編輯:PHP 相關知識

Session 儲存機制由 `session.save_handler` 決定。預設 `files` 以檔案儲存;`user` 允許完全自定義六個回調函數,支援 Redis、資料庫、Memcached 等集中式儲存。本文對比兩者流程並給出自定義 Handler 完整範本。

Handler = files:標準檔案流程

  1. `session_start()`**:
    • 按 `gc_probability/gc_divisor` 機率觸發 GC 掃描 `save_path` 刪除過期檔 (`gc_maxlifetime` 預設 1440s)。
    • 檢查 Cookie `$_COOKIE[session_name()]` (預設 `PHPSESSID`)。
    • 有 ID → 讀取 `save_path/sess_{id}` 反序列化填 `$_SESSION`。
    • 無 ID → 生成新 ID、`setcookie()` 下發、建立空檔案。
  2. 賦值 `$_SESSION['k']='v'`**:僅修改記憶體中 `$_SESSION` 陣列。
  3. 腳本結束 (RSHUTDOWN)**:序列化 `$_SESSION` 寫入 `sess_{id}` 檔案,關閉資源。
  4. ID 重生/銷毀**:
    • `session_regenerate_id(true)`:舊檔刪除、新 ID 下發 Cookie。
    • `session_destroy()`:刪除 `$_SESSION`、刪除檔案、刪除 Cookie。

關鍵配置陷阱

  • `save_path = "N;/path"` 隨機分級目錄:**GC 失效**,需自寫腳本清理。
  • Windows 預設 `save_path` 可能指向不存在目錄 → Session 失效。
  • 叢集環境**必須**改用集中式儲存 (Redis/DB),否則 Session 不共享。

Handler = user:自定義回調完整簽名

session_set_save_handler(
    'open',    // open($savePath, $sessionName) : bool
    'close',   // close() : bool
    'read',    // read($id) : string (返回序列化資料)
    'write',   // write($id, $data) : bool
    'destroy', // destroy($id) : bool
    'gc'       // gc($maxLifetime) : bool
);
// PHP 5.4+ 可傳入實作 SessionHandlerInterface 的物件

流程對應

  • `session_start()` → `open()` → `read($id)`
  • 腳本結束 → `write($id, $serializedData)` → `close()`
  • `session_destroy()` → `destroy($id)` → (結束流程)
  • GC 觸發 → `gc($maxLifetime)`

自定義 Handler 範本:檔案版 (教學用,生產請用 Redis/DB)

<?php
class FileSessionHandler implements SessionHandlerInterface {
    private $savePath;

    public function open($savePath, $sessionName): bool {
        $this->savePath = $savePath;
        if (!is_dir($savePath)) mkdir($savePath, 0777, true);
        return true;
    }
    public function close(): bool { return true; }

    public function read($id): string {
        $file = $this->savePath . "/sess_$id";
        return (string)@file_get_contents($file);
    }

    public function write($id, $data): bool {
        $file = $this->savePath . "/sess_$id";
        $fp = @fopen($file, 'w');
        if (!$fp) return false;
        $ret = fwrite($fp, $data);
        fclose($fp);
        return $ret !== false;
    }

    public function destroy($id): bool {
        $file = $this->savePath . "/sess_$id";
        return @unlink($file);
    }

    public function gc($maxLifetime): bool {
        foreach (glob($this->savePath . "/sess_*") as $file) {
            if (filemtime($file) + $maxLifetime < time()) @unlink($file);
        }
        return true;
    }
}

// 註冊
$handler = new FileSessionHandler();
session_set_save_handler($handler, true); // true = 註冊 shutdown function
session_start();
// 正常使用 $_SESSION
?>

生產級 Redis Handler 關鍵點

  • `read`:`GET session:{id}` → 返回資料或 `''`。
  • `write`:`SETEX session:{id} {ttl} {data}` (TTL = `maxLifetime`),原子寫入+過期。
  • `destroy`:`DEL session:{id}`。
  • `gc`:**不需要**,Redis 自動過期淘汰。
  • 連線池、序列化 (igbinary/msgpack)、鎖機制 (防併發覆蓋) 是進階優化方向。

掌握 Handler 機制,就能將 Session 從本地檔案解脫,構建高可用、水平擴展的分散式 Session 架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved