PHP Session 原生支援儲存物件,引擎會自動在請求結束時 序列化 物件,下一請求 反序列化 還原。關鍵在於:類別定義必須在 session_start() 之前載入,否則會變成 __PHP_Incomplete_Class 無法存取屬性方法。
session_start() 前 require_once。public 或實作 __sleep/__wakeup 控制序列化行為。<?php
// Person.php
class Person {
public string $name;
public string $email;
public function __construct(string $name, string $email) {
$this->name = $name;
$this->email = $email;
}
public function cleanName(): string {
return preg_replace('/\s+/', ' ', trim($this->name));
}
// 選擇性:控制序列化內容
public function __sleep(): array {
return ['name', 'email']; // 僅儲存這兩個屬性
}
public function __wakeup(): void {
// 反序列化後初始化(如重新建立資料庫連線)
}
}
?>
<?php
require_once 'Person.php';
session_start();
if (!isset($_SESSION['user'])) {
$_SESSION['user'] = new Person('Item Raja', 'itemraja@php.net');
}
header('Location: dashboard.php');
<?php
require_once 'Person.php'; // 必須在 session_start 前載入!
session_start();
$user = $_SESSION['user'] ?? null;
if ($user instanceof Person) {
echo "歡迎, {$user->cleanName()} ({$user->email})";
} else {
header('Location: login.php');
}
?>
class Person implements Serializable {
// ...
public function serialize(): string {
return json_encode(['name' => $this->name, 'email' => $this->email]);
}
public function unserialize(string $data): void {
$arr = json_decode($data, true);
$this->name = $arr['name'];
$this->email = $arr['email'];
}
}
| 現象 | 原因 | 解決 |
|---|---|---|
| 變成 __PHP_Incomplete_Class | session_start 前未載入類別 | 調整 require_once 順序 |
| 私有屬性丟失 | 預設序列化包含所有非 static 屬性 | 實作 __sleep 明確列出 |
| 資源屬性導致錯誤 | 資源無法序列化 | __sleep 排除、__wakeup 重建 |
| 大型物件佔用 Session 儲存空間 | 序列化後字串過長 | 僅儲存 ID,需時從 DB/快取載入 |