PHP Session存储含私有属性的对象数组刷新后失效问题
问题根源
问题核心是类属性声明错误,和Session序列化机制本身无关。
你在Month类中将$mes、$year声明为了private static静态属性:
class Month{ private static $mes; private static $year; // 其余代码省略 }
静态属性归属于类本身,不归属于单个对象实例,PHP在序列化/反序列化Session中的对象时,只会处理实例属性,不会保存和恢复静态属性的值:
- 首次访问页面时,构造函数给
$this->mes、$this->year赋值时,类中没有声明对应的实例属性,PHP会自动为对象创建动态公共属性,所以首次var_dump看到的属性是无类访问标记的["mes"]=> string(1) "4"格式,方法调用也能正常读值。 - 刷新页面时,PHP从Session存储中反序列化恢复Month对象,之前动态生成的公共属性不会被还原(类中仅声明了静态私有属性,无对应实例属性),反序列化后的对象实例属性为空,调用
getMes()、toString()等方法时无法取到正确值,功能随即异常。
你之前将属性改为public即可正常运行,本质是误将静态属性改成了实例属性,符合序列化要求——private修饰的实例属性本身完全可以正常序列化存入Session,和访问权限修饰符没有关系。
修复方案
- 修正Month类的属性声明,去掉
static关键字,将静态属性改为私有实例属性:
<?php class Month{ // 移除static关键字,声明为私有实例属性 private $mes; private $year; static function void(){ return new self(null, null); } function __construct($mes, $year){ $this->mes = $mes; $this->year = $year; } // GETTERS public function getMes(){ return $this->mes; } public function getYear(){ return $this->year; } //SETTERS public function setMes($mes){ $this->mes = $mes; } public function setYear($year){ $this->year = $year; } //Métodos public function toString(){ switch ($this->mes) { case 1: return "Enero - ".$this->year; case 2: return "Febrero - ".$this->year; case 3: return "Marzo - ".$this->year; case 4: return "Abril - ".$this->year; case 5: return "Mayo - ".$this->year; case 6: return "Junio - ".$this->year; case 7: return "Julio - ".$this->year; case 8: return "Agosto - ".$this->year; case 9: return "Septiembre - ".$this->year; case 10: return "Octubre - ".$this->year; case 11: return "Noviembre - ".$this->year; case 12: return "Diciembre - ".$this->year; default: return ""; } } }
- 清理旧的错误Session数据:
- 可临时在
session_start()后添加一行$_SESSION = [];,刷新一次页面清除旧缓存后再删除该行代码即可; - 也可以直接清除浏览器对应站点的Cookie,让服务端生成全新Session。
验证说明
修改完成后,无论首次访问还是刷新页面,var_dump输出的对象属性都会是带私有标记的["mes":"Month":private]格式,调用getMes()、toString()方法均可正常取值,不需要将属性改为public,也不需要额外编写自定义序列化逻辑,PHP原生支持私有属性的对象在Session中正常存取。
内容的提问来源于stack exchange,提问作者icortazar
相关产品推荐
相关产品推荐

