yii 1.x 中 session 不需 session_start(),但必须通过 yii::app()->session 操作;autostart=false 时须手动 open(),登出需先 clear() 再 destroy(),数据库存储须同时配置 class 和 connectionid。

Yii 1.x 中的 session 不需要手动调用 session_start(),但直接读写 $_SESSION 是危险且不可靠的——它绕过框架生命周期、可能被自动清理机制忽略,甚至在某些配置下(如 autoStart => false)导致空 session。
Yii::app()->session 基本读写必须先确保 autoStart
默认情况下 'autoStart' => true,所以大多数场景下你只需:
Yii::app()->session['user_id'] = 123;$uid = Yii::app()->session['user_id'];unset(Yii::app()->session['user_id']);
但如果在 main.php 的 components['session'] 中显式设了 'autoStart'=>false,上述操作会静默失败(不报错,但值不存也不读)。此时必须手动触发:Yii::app()->session->open(); 才能开始读写。常见于自定义 session 存储(如 DB 或 Redis)且需延迟初始化的场景。
clear() 和 destroy() 的区别不能混用
用户登出时,仅调用 clear() 不够安全:
-
Yii::app()->session->clear():只清空当前请求中已加载的 session 变量(即内存副本),服务器端存储(文件/DB)仍保留原始数据 -
Yii::app()->session->destroy():真正删除服务端 session 文件或数据库记录,并使该sessionID失效 - 正确登出顺序应为:
Yii::app()->session->clear(); Yii::app()->session->destroy();
漏掉 destroy() 可能导致 session 回收延迟,攻击者若拿到旧 sessionID(比如从日志或未清除的 cookie 中获取),仍可重放会话。
数据库存 session 必须配对设置 class 和 connectionID
把 session 存到数据库不是改个路径就行,关键两项缺一不可:
-
'class' => 'system.web.CDbHttpSession':必须指定这个类,否则框架仍走默认文件存储 -
'connectionID' => 'db':必须指向一个已正确定义的数据库组件 ID(比如你在components里定义了'db'=>array('class'=>'CDbConnection',...)) - 可选但建议加:
'sessionTableName' => 'tbl_session',并确保该表结构符合 Yii 要求(含id、expire、data字段)
如果只改 class 没配 connectionID,启动时会抛出 CDbHttpSession.connectionID is invalid 错误;如果表结构不对,写入会静默失败,但读不到数据。
调试 sessionID 和遍历变量要避开 foreach($_SESSION)
Yii::app()->session->sessionID 是唯一可靠方式获取当前 session 标识符。不要依赖 session_id(),因为 Yii 可能尚未 open 或已 close,返回空字符串。
遍历所有 session 变量,应该用:
foreach (Yii::app()->session as $key => $value) {
var_dump($key, $value);
}
而不是 foreach ($_SESSION as ...)——后者在 autoStart => false 或 session 尚未 open 时为空数组,且无法反映 Yii 内部对 flash、timeout 等特殊字段的管理逻辑。
session 的实际行为高度依赖 autoStart 开关和组件初始化时机,很多问题不是代码写错,而是没意识到 Yii 的 session 是懒加载+封装对象,不是全局数组的简单别名。










