session_set_save_handler

(PHP 4, PHP 5, PHP 7, PHP 8)

session_set_save_handler設(shè)置用戶自定義會話存儲函數(shù)

說明

session_set_save_handler(
    callable $open,
    callable $close,
    callable $read,
    callable $write,
    callable $destroy,
    callable $gc,
    callable $create_sid = ?,
    callable $validate_sid = ?,
    callable $update_timestamp = ?
): bool

可以使用下面的方式來注冊自定義會話存儲函數(shù):

session_set_save_handler(object $sessionhandler, bool $register_shutdown = true): bool

session_set_save_handler() 設(shè)置用戶自定義 會話存儲函數(shù)。 如果想使用 PHP 內(nèi)置的會話存儲機制之外的方式, 可以使用本函數(shù)。 例如,可以自定義會話存儲函數(shù)來將會話數(shù)據(jù)存儲到數(shù)據(jù)庫。

參數(shù)

本函數(shù)有 2 種原型:

sessionhandler

實現(xiàn)了 SessionHandlerInterfaceSessionIdInterface(可選) 和/或 SessionUpdateTimestampHandlerInterface 接口的對象, 例如 SessionHandler。

register_shutdown

將函數(shù) session_write_close() 注冊為 register_shutdown_function() 函數(shù)。

或者
open(string $savePath, string $sessionName)

實現(xiàn)了以下簽名的 callable 回調(diào):

open(string $savePath, string $sessionName): bool

open 回調(diào)函數(shù)類似于類的構(gòu)造函數(shù), 在會話打開的時候會被調(diào)用。 這是自動開始會話或者通過調(diào)用 session_start() 手動開始會話 之后第一個被調(diào)用的回調(diào)函數(shù)。 此回調(diào)函數(shù)操作成功返回 true,反之返回 false

close

close 回調(diào)函數(shù)類似于類的析構(gòu)函數(shù)。 在 write 回調(diào)函數(shù)調(diào)用之后調(diào)用。 當調(diào)用 session_write_close() 函數(shù)之后,也會調(diào)用 close 回調(diào)函數(shù)。 此回調(diào)函數(shù)操作成功返回 true,反之返回 false

read

實現(xiàn)了以下簽名的 callable 回調(diào):

read(string $sessionId): string

如果會話中有數(shù)據(jù),read 回調(diào)函數(shù)必須返回將會話數(shù)據(jù)編碼(序列化)后的字符串。 如果會話中沒有數(shù)據(jù),read 回調(diào)函數(shù)返回空字符串。

在自動開始會話或者通過調(diào)用 session_start() 函數(shù)手動開始會話之后,PHP 內(nèi)部調(diào)用 read 回調(diào)函數(shù)來獲取會話數(shù)據(jù)。 在調(diào)用 read 之前,PHP 會調(diào)用 open 回調(diào)函數(shù)。

read 回調(diào)返回的序列化之后的字符串格式必須與 write 回調(diào)函數(shù)保存數(shù)據(jù)時的格式完全一致。 PHP 會自動反序列化返回的字符串并填充 $_SESSION 超級全局變量。 雖然數(shù)據(jù)看起來和 serialize() 函數(shù)很相似, 但是需要提醒的是,它們是不同的。 請參考: session.serialize_handler

write

實現(xiàn)了以下簽名的 callable 回調(diào):

write(string $sessionId, string $data): bool

在會話保存數(shù)據(jù)時會調(diào)用 write 回調(diào)函數(shù)。 此回調(diào)函數(shù)接收當前會話 ID 以及 $_SESSION 中數(shù)據(jù)序列化之后的字符串作為參數(shù)。 序列化會話數(shù)據(jù)的過程由 PHP 根據(jù) session.serialize_handler 設(shè)定值來完成。

序列化后的數(shù)據(jù)將和會話 ID 關(guān)聯(lián)在一起進行保存。 當調(diào)用 read 回調(diào)函數(shù)獲取數(shù)據(jù)時,所返回的數(shù)據(jù)必須要和 傳入 write 回調(diào)函數(shù)的數(shù)據(jù)完全保持一致。

PHP 會在腳本執(zhí)行完畢或調(diào)用 session_write_close() 函數(shù)之后調(diào)用此回調(diào)函數(shù)。 注意,在調(diào)用完此回調(diào)函數(shù)之后,PHP 內(nèi)部會調(diào)用 close 回調(diào)函數(shù)。

注意:

PHP 會在輸出流寫入完畢并且關(guān)閉之后 才調(diào)用 write 回調(diào)函數(shù), 所以在 write 回調(diào)函數(shù)中的調(diào)試信息不會輸出到瀏覽器中。 如果需要在 write 回調(diào)函數(shù)中使用調(diào)試輸出, 建議將調(diào)試輸出寫入到文件。

destroy

實現(xiàn)了以下簽名的 callable 回調(diào):

destroy(string $sessionId): bool

當調(diào)用 session_destroy() 函數(shù), 或者調(diào)用 session_regenerate_id() 函數(shù)并且設(shè)置 destroy 參數(shù)為 true 時, 會調(diào)用此回調(diào)函數(shù)。此回調(diào)函數(shù)操作成功返回 true,反之返回 false。

gc

實現(xiàn)了以下簽名的 callable 回調(diào):

gc(int $lifetime): bool

為了清理會話中的舊數(shù)據(jù),PHP 會不時的調(diào)用垃圾收集回調(diào)函數(shù)。 調(diào)用周期由 session.gc_probabilitysession.gc_divisor 參數(shù)控制。 傳入到此回調(diào)函數(shù)的 lifetime 參數(shù)由 session.gc_maxlifetime 設(shè)置。 此回調(diào)函數(shù)操作成功返回 true,反之返回 false

create_sid

實現(xiàn)了以下簽名的 callable 回調(diào):

create_sid(): string

需要新的會話 ID 時,執(zhí)行此回調(diào)函數(shù)。 它被調(diào)用時不會傳入?yún)?shù),其返回值應(yīng)該是一個字符串格式的、有效的 session ID。

validate_sid

實現(xiàn)了以下簽名的 callable 回調(diào):

validate_sid(string $key): bool

開啟 session.use_strict_mode 后, 當啟動一個 session 時,提供了 session ID 后會執(zhí)行此回調(diào)。 參數(shù) key 是待驗證的 session ID。 如果該 ID 的 session 已經(jīng)存在,則為有效 session ID。 成功時返回值應(yīng)當為 true,失敗時為 false

update_timestamp

實現(xiàn)了以下簽名的 callable 回調(diào):

update_timestamp(string $key, string $val): bool

更新 session 時執(zhí)行此回調(diào)。 參數(shù) key 是 session ID;參數(shù) val 是 session 的數(shù)據(jù)。 成功時返回值應(yīng)當為 true,失敗時為 false。

返回值

成功時返回 true, 或者在失敗時返回 false。

范例

示例 #1 自定義會話管理器: 完整代碼請參見 SessionHandlerInterface。

這里僅列出了調(diào)用方式,完整代碼請參見 SessionHandlerInterface。

這里使用了 session_set_save_handler() 函數(shù)的 OOP 原型 并且使用第二個參數(shù)來注冊 shutdown 函數(shù)。 當將對象注冊為會話保存管理器時,建議使用這種方式。

<?php
class MySessionHandler implements SessionHandlerInterface
{
    
// 在這里實現(xiàn)接口
}

$handler = new MySessionHandler();
session_set_save_handler($handlertrue);
session_start();

// 現(xiàn)在可以使用 $_SESSION 保存以及獲取數(shù)據(jù)了

注釋

警告

在對象銷毀之后才會調(diào)用 writeclose 回調(diào)函數(shù), 所以,在這兩個回調(diào)函數(shù)中不可以使用對象,也不可以拋出異常。 如果在函數(shù)中拋出異常,PHP 既不會捕獲它,也不會跟蹤它, 這樣會導致程序異常終止。 但是對象析構(gòu)函數(shù)可以使用會話。

可以在析構(gòu)函數(shù)中調(diào)用 session_write_close() 函數(shù)來解決這個問題。 但是注冊 shutdown 回調(diào)函數(shù)才是更加可靠的做法。

警告

如果會話在腳本結(jié)束后關(guān)閉,對于某些 SAPI 而言,當前工作目錄可能已經(jīng)被改變。 可以調(diào)用 session_write_close() 函數(shù)在腳本執(zhí)行結(jié)束之前關(guān)閉會話。

參見