Yii 透過 yii\web\Session 元件管理 Session,yii\web\Cookie 物件代表單一 Cookie,由 Request 與 Response 的 cookies 集合分別處理讀取與發送。本文詳細說明開啟關閉、資料存取、自訂儲存、閃爍資料、Cookie 驗證等實務操作。
$session = Yii::$app->session; if ($session->isActive) ... $session->open(); $session->close(); $session->destroy();
重複呼叫 open()/close() 不會報錯,內部已檢查狀態。
$session = Yii::$app->session;
// 讀取
$language = $session->get('language');
$language = $session['language'];
// 寫入
$session->set('language', 'en-US');
$session['language'] = 'en-US';
// 刪除
$session->remove('language');
unset($session['language']);
// 檢查存在
$session->has('language');
isset($session['language']);
// 遍歷
foreach ($session as $name => $value) ...
使用元件存取時若 Session 未開啟會自動開啟,異於直接操作 $_SESSION 需先呼叫 session_start()。
直接修改陣列元素 $session['captcha']['number'] = 5 不生效,解決方式:
$_SESSION(確保已 open())ArrayObjectcaptcha.number、captcha.lifetime),效能與可讀性最佳Yii 提供多種儲存類別,API 一致,切換無需修改業務代碼:
yii\web\DbSession:資料庫資料表yii\web\CacheSession:快取元件yii\redis\Session:Redisyii\mongodb\Session:MongoDBreturn [
'components' => [
'session' => [
'class' => 'yii\web\DbSession',
// 'db' => 'mydb',
// 'sessionTable' => 'my_session',
],
],
];
需建立資料表:
CREATE TABLE session (
id CHAR(40) NOT NULL PRIMARY KEY,
expire INTEGER,
data BLOB
);
注意 session.hash_function 影響 id 欄位長度(sha256 需 64 字元)。
僅在下一次請求有效,適合一次性提示訊息:
$session = Yii::$app->session;
// 請求 #1 設定
$session->setFlash('postDeleted', '刪除成功');
// 請求 #2 讀取並自動刪除
echo $session->getFlash('postDeleted');
// 請求 #3 已不存在
$result = $session->hasFlash('postDeleted'); // false
addFlash() 可同名累加多筆資料為陣列,避免與 setFlash() 混用造成型態不一致。
$cookies = Yii::$app->request->cookies;
$language = $cookies->getValue('language', 'en');
if (($cookie = $cookies->get('language')) !== null) {
$language = $cookie->value;
}
if (isset($cookies['language'])) {
$language = $cookies['language']->value;
}
$cookies = Yii::$app->response->cookies;
$cookies->add(new \yii\web\Cookie([
'name' => 'language',
'value' => 'zh-CN',
]));
$cookies->remove('language');
// 或 unset($cookies['language']);
可設定 domain、expire 等屬性。預設 httpOnly = true 降低 XSS 風險。
預設啟用,透過簽章防止客戶端竄改。驗證失敗的 Cookie 不會出現在 Request::cookies,但仍可透過 $_COOKIE 存取。必須設定 cookieValidationKey:
return [
'components' => [
'request' => [
'cookieValidationKey' => '填入金鑰',
],
],
];
金鑰關乎安全,勿納入版控。