codeigniter 的 session 必须正确初始化:ci3 需在 parent::__construct() 后加载 session 库,ci4 用 session() 函数获取实例;密钥未配置或为空会导致静默失效;购物车应存轻量数据并避免 flashdata;redis 并发需手动加锁;务必验证 session 实例有效性。

CodeIgniter 的 Session 不是“加载就能用”,它必须在正确时机、以正确方式初始化,否则 $this->session 会是 null 或静默失效——登录态丢、购物车空、flashdata 不显示,问题都出在这一步。
CI3 和 CI4 的 session() 函数完全不兼容
别看到 session() 就直接调;先确认版本:composer show codeigniter4/framework 或查 system/CodeIgniter.php 文件头。CI3 没这个函数,写了就报 Fatal error: Call to undefined function session();CI4 才有,且它不是辅助函数,是服务工厂函数,返回一个已启动的 Session 实例。
- CI3 必须用
$this->load->library('session'),且必须在parent::__construct()之后调用 - CI4 推荐直接写
$session = session();,哪怕在模型或库中也能用,无需依赖控制器上下文 - CI4 中
$this->session默认为null,除非你手动注入或显式赋值——这不是 bug,是设计
加密密钥没配,session 就算加载了也白搭
CI3 要求 $config['encryption_key'] 非空,否则 set_userdata() 看似成功,实际数据根本没加密写入 cookie,userdata() 返回空数组,还不报错。CI4 改用 app/Config/Encryption.php 中的 $key,默认已生成,但如果你手动清空或覆盖了它,同样会静默失败。
- CI3:打开
application/config/config.php,确认这行不为空:$config['encryption_key'] = 'a-32-character-random-string-here'; - CI4:检查
app/Config/Encryption.php中public $key是否为非空字符串,不要设成null或空字符串 - 密钥改过之后,旧 session 全部失效——这是正常行为,不是 bug
存购物车别塞整个数组,会超 cookie 限制
用 $this->session->set_userdata('cart', $big_array) 是典型反模式。CI3 默认开启 sess_encrypt_cookie = TRUE,加密后 cookie 容量上限约 4KB;大购物车一存,cookie 被浏览器截断,set_userdata() 表面不报错,实际写入失败。
- 只存轻量映射:
$this->session->set_userdata('cart_items', ['101' => 2, '102' => 1]); - 商品详情(名称、价格、库存)全部从数据库实时查,避免 session 过期后数据陈旧
- 加购逻辑要原子化:
$cart = $this->session->userdata('cart_items') ?: [];→ 修改 →set_userdata()全量写回 - 别用
flashdata存购物车——它只活一次请求,刷新页面就空了
Redis 驱动下 session 更新可能被并发覆盖
CI3 的 Redis 驱动默认无锁;两个 AJAX 请求同时读-改-写购物车数量,后写的会覆盖前写的。比如用户点两次“+1”,最终数量只 +1。
- 启用 Redis 锁需自行实现,CI 原生不提供;可用
SET key value EX seconds NX做简易乐观锁 - 更稳妥的做法是把购物车状态下沉到数据库,session 只做未登录用户的临时缓存
- CI4 的 Redis 驱动在 4.4+ 版本开始支持
lock选项,但需手动配置$config['sess_locking_enabled'] = TRUE;
session 最容易被忽略的不是怎么存,而是怎么验证它真正在工作——加一行 var_dump($session instanceof \CodeIgniter\Session\Session); 或 var_dump($this->session !== null);,比猜三天报错原因快得多。











