ThinkPHP 以單一 session() 函數實現 Session 全生命週期管理,定義於 Common/functions.php。通過參數類型與特殊字符串區分操作模式:
'[start]'、'[pause]'、'[destroy]'、'[regenerate]' → 控制指令'?name' → 檢查存在性// 配置陣列參數
$config = [
'name' => 'MYSESSID', // session_name()
'path' => '/tmp/session', // session_save_path()
'domain' => '.example.com', // cookie_domain
'expire' => 3600, // gc_maxlifetime & cookie_lifetime
'use_trans_sid' => 0, // URL 透傳 SID
'use_cookies' => 1, // 使用 Cookie
'cache_limiter' => 'nocache',
'cache_expire' => 180,
'type' => 'Mysql', // 驅動類型:File/Mysql/Redis/Memcache
'prefix' => 'tp_', // 鍵名前綴
'id' => 'custom_session_id' // 指定 session_id
];
session($config);
核心初始化邏輯(節選):
if (is_array($name)) {
// 設置 session_name、save_path、cookie_domain 等 ini 選項
if (isset($name['expire'])) {
ini_set('session.gc_maxlifetime', $name['expire']);
ini_set('session.cookie_lifetime', $name['expire']);
}
// 驅動處理器註冊
if (C('SESSION_TYPE')) {
$type = C('SESSION_TYPE');
$class = 'Think\\Session\\Driver\\' . ucwords(strtolower($type));
$handler = new $class();
session_set_save_handler(
[$handler, 'open'], [$handler, 'close'],
[$handler, 'read'], [$handler, 'write'],
[$handler, 'destroy'], [$handler, 'gc']
);
}
// 自動啟動
if (C('SESSION_AUTO_START')) session_start();
}
通過配置 SESSION_TYPE 切換:
// 配置文件 'SESSION_TYPE' => 'Mysql', // 或 Redis, Memcache // MySQL 需建表:think_session (sess_id, sess_data, sess_time) // Redis/Memcache 需對應擴展支援
| 操作 | 代碼 | 等價原生 PHP |
|---|---|---|
| 啟動 | session('[start]') | session_start() |
| 暫停寫入 | session('[pause]') | session_write_close() |
| 銷毀 | session('[destroy]') | session_destroy() + 清空 $_SESSION |
| 重新生成 ID | session('[regenerate]') | session_regenerate_id() |
| 寫入單值 | session('user.name', '張三') | $_SESSION['user']['name'] = '張三' |
| 讀取單值 | session('user.name') | $_SESSION['user']['name'] ?? null |
| 讀取全部 | session() | $_SESSION |
| 刪除單值 | session('user.name', null) | unset($_SESSION['user']['name']) |
| 清空前綴 | session(null) | unset($_SESSION['prefix']) |
| 檢查存在 | session('?user.name') | isset($_SESSION['user']['name']) |
ThinkPHP 以 . 分隔多級鍵:
session('user.profile.avatar', 'url'); // 寫入
$avatar = session('user.profile.avatar'); // 讀取
session('user.profile.avatar', null); // 刪除
// 內部實現:explode('.', $name) → 兩級陣列操作
// 配置 'SESSION_PREFIX' => 'home_', // 實際存儲鍵名 $_SESSION['home_']['user']['name'] = 'value';
class Auth {
const KEY = 'auth_user';
public static function login($userId) {
$user = UserModel::find($userId);
session(self::KEY, [
'id' => $user->id,
'name' => $user->username,
'role' => $user->role,
'login_time' => time()
]);
session('[regenerate]'); // 防固定攻擊
}
public static function user() {
return session(self::KEY);
}
public static function check() {
return session('?' . self::KEY);
}
public static function logout() {
session(self::KEY, null);
session('[destroy]');
}
}
function flash($key, $value = null) {
if ($value !== null) {
session('_flash_' . $key, $value);
} else {
$val = session('_flash_' . $key);
session('_flash_' . $key, null);
return $val;
}
}
// 控制器
flash('success', '操作成功!');
redirect('/list');
// 視圖
= $msg ?>
| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| Session 不生效 | 未啟動、Cookie 被禁、域名不匹配 | 檢查 session('[start]')、session.use_cookies=1、cookie_domain |
| 跨子域名共享失敗 | cookie_domain 未設置 | 設置 'domain' => '.example.com' |
| 集群環境 Session 丟失 | 文件存儲非共享 | 改用 Redis/MySQL 驅動,配置共享存儲 |
| 並發請求阻塞 | Session 文件鎖 | 盡早 session('[pause]') 釋放鎖,或用 Redis 非阻塞驅動 |
session() 統一入口,參數多態設計簡潔優雅[pause] 釋放鎖、[regenerate] 防劫持等進階用法ThinkPHP Session 封裝屏蔽了底層複雜性,提供了符合直覺的 API。深入理解其配置與驅動機制,能靈活應對從單機到分佈式的各種場景需求。