bool session_set_save_handler(
callable $open,
callable $close,
callable $read,
callable $write,
callable $destroy,
callable $gc
)
CREATE TABLE `session` (
`session_key` CHAR(32) NOT NULL PRIMARY KEY,
`session_data` TEXT NOT NULL,
`session_expiry` INT(11) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
<?php
class SessionHandler {
private $expiry = 3600; // 1 小時
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
session_set_save_handler(
[$this, 'open'],
[$this, 'close'],
[$this, 'read'],
[$this, 'write'],
[$this, 'destroy'],
[$this, 'gc']
);
session_start();
}
public function open($savePath, $sessionName) {
// PDO 已在建構式連線,這裡可做額外初始化
return true;
}
public function close() {
return true; // 持久連線不關閉
}
public function read($key) {
$stmt = $this->pdo->prepare(
"SELECT session_data FROM session WHERE session_key = ? AND session_expiry > ?"
);
$stmt->execute([$key, time()]);
$row = $stmt->fetch(PDO::FETCH_COLUMN);
return $row ?: '';
}
public function write($key, $data) {
$expiry = time() + $this->expiry;
$stmt = $this->pdo->prepare(
"INSERT INTO session (session_key, session_data, session_expiry) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE session_data = VALUES(session_data), session_expiry = VALUES(session_expiry)"
);
return $stmt->execute([$key, $data, $expiry]);
}
public function destroy($key) {
$stmt = $this->pdo->prepare("DELETE FROM session WHERE session_key = ?");
return $stmt->execute([$key]);
}
public function gc($maxLifetime) {
$stmt = $this->pdo->prepare("DELETE FROM session WHERE session_expiry < ?");
return $stmt->execute([time()]);
}
}
// 使用
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
new SessionHandler($pdo);
$_SESSION['time'] = time() + 1200;
echo time() . '<br>' . $_SESSION['time'];
?>
| 項目 | 原始版本 | 現代版本 |
|---|---|---|
| 資料庫介面 | mysql_* (已移除) | PDO (Prepared Statements) |
| SQL Injection | 直接拼接,高風險 | 參數綁定,安全 |
| 字元集 | utf8 | utf8mb4 (支援 Emoji) |
| 資料表引擎 | MyISAM | InnoDB (交易、行鎖) |
| 資料型別 | CHAR(255) 截斷風險 | TEXT 無長度限制 |
| GC 效能 | 全表掃描 | 索引 session_expiry 加速 |
CREATE INDEX idx_expiry ON session(session_expiry)session_write_close() 早釋放鎖第零空間版權所有