開發者常遇到:明明在 A 頁面 $_SESSION['user'] = 'John';,跳轉到 B 頁面卻讀不到值。這通常不是 Session 本身壞了,而是 **Session ID 未正確傳遞** 導致伺服器找不到對應的儲存檔案。
Session 資料儲存在伺服器(預設為檔案),客戶端只持有 **Session ID**。流程如下:
session_start() → 伺服器建立 session 檔案,生成唯一 Session ID。若 Cookie 被禁用、瀏覽器故障,或 PHP 設定 session.use_trans_sid = 0,Session ID 就無法傳遞,導致每次 session_start() 都建立**新** session,自然讀不到舊資料。
設定 session.use_trans_sid = 1 或編譯 PHP 時加入 --enable-trans-sid。PHP 會自動將 Session ID 附加在 URL 查詢字串(如 ?PHPSESSID=abc123)或表單隱藏欄位中。
<?php
// s1.php
session_start();
$_SESSION['var1'] = "中華人民共和國";
echo '<a href="s2.php">下一頁</a>';
?>
<?php
// s2.php
session_start();
echo "傳遞的 session 變數 var1 值為:" . $_SESSION['var1'];
?>
關閉 Cookie 測試:若設定正確,仍能正常顯示數值。
不依賴 php.ini 設定,開發者自行控制:
<?php
// s1.php
session_start();
$_SESSION['var1'] = "中華人民共和國";
$sn = session_id();
echo '<a href="s2.php?s=' . $sn . '">下一頁</a>';
?>
<?php
// s2.php
session_id($_GET['s']); // 必須在 session_start() 之前
session_start();
echo "傳遞的 session 變數 var1 值為:" . $_SESSION['var1'];
?>
隱藏表單同理:<input type="hidden" name="PHPSESSID" value="<?php echo session_id(); ?>">
適用於完全不依賴 Cookie、且不想暴露 Session ID 在 URL 的場景。
<?php
// mylogin1.php 登入驗證成功後
session_start();
$_SESSION['user'] = $name;
$psid = session_id();
$fp = fopen("e:/tmp/phpsid.txt", "w+");
fwrite($fp, $psid);
fclose($fp);
echo '<a href="mylogin2.php">下一頁</a>';
?>
<?php
// mylogin2.php
$fp = fopen("e:/tmp/phpsid.txt", "r");
$sid = fread($fp, 1024);
fclose($fp);
session_id($sid); // 先設定 ID
session_start(); // 再啟動
if (isset($_SESSION['user']) && $_SESSION['user'] == "laogong") {
echo "已登入!";
} else {
echo "未登入,請<a href='login.html'>登入</a>";
}
?>
生產環境建議將 Session ID 存入資料庫(關聯 user_id),並設定過期時間,避免檔案鎖定與併發問題。
| 誤區 | 正確做法 |
|---|---|
| 以為 Session 必須依賴 Cookie | Session 可透過 URL、表單、資料庫傳遞 ID |
在 session_start() 後才設定 session_id() | 必須在 session_start() **之前** 呼叫 session_id($id) |
| 跨子域名 Session 不共享 | 設定 session.cookie_domain = ".example.com" |
| 多伺服器負載均衡 Session 失效 | 使用 Redis/Memcached 集中式 Session 儲存 |
Session 跨頁失效的本質是 **Session ID 傳遞中斷**。解決核心只有一點:**在下一頁 session_start() 前,確保正確的 Session ID 已被設定**。根據專案架構選擇:
session.use_trans_sid。掌握這三種途徑,Session 問題將不再是困擾。