PHP 8.3 语法变化 - unserialize 将 E_NOTICE 错误升级为 E_NOTICE 错误
hi,我是温新,一名 PHPer
PHP提供 serialize
和 unserialize
函数来序列化任何 PHP 值(字符串、整数、对象、NULL、数组、枚举等)。转换为字符串表示,并从该字符串表示重新创建 PHP 值。
$data = ['apple', 'banana', 'orange'];
$serialized = serialize($data);
// "a:3:{i:0;s:5:"apple";i:1;s:6:"banana";i:2;s:6:"orange";}"
$restoredData = unserialize($serialized);
// ['apple', 'banana', 'orange']
在 PHP 8.3 之前,将无效字符串传递给 unserialize() 函数在某些情况下会发出 PHP 通知(E_NOTICE),例如序列化字符串中的语法错误。自 PHP 8.3 及更高版本起,此情况已更改为发出警告(E_WARNING)。此外,serialize()
函数的某些错误条件也已更改为发出 E_WARNING。
unserialize("invalid-string");
PHP Warning: unserialize(): Error at offset 0 of 14 bytes
理想情况下,无法反序列化给定字符串应该是一个硬失败,并抛出一个异常。然而,为了保持向后兼容并简化升级路径,在 PHP 8.3 中提高了错误级别,未来可能会升级为抛出异常。
错误条件不一致
并非所有的
unserialize()
失败都会发出 E_NOTICE 错误。例如,反序列化超过最大深度限制的字符串(自 PHP 7.4 起使用unserialize_max_depth INI
设置进行配置)已经发出 E_WARNING。此情况继续发出 E_WARNING 错误,并且没有改变。
受影响的错误条件
自 PHP 8.3 起,以下三个之前发出 E_NOTICE 的错误条件更改为发出 E_WARNING:
-
传递的字符串中的语法错误(有时由错误的序列化处理程序引起)
unserialize('invalid string');
PHP Warning: unserialize(): Error at offset 0 of 12 bytes
-
使用 __unserialize 魔术方法的自定义 unserialize 处理程序失败;例如,__unserialize() 方法未返回任何值。
class Test { public function __unserialize(array $data) { } // Does not return anything }
PHP Warning: unserialize(): Unexpected end of serialized data
-
从 __sleep() 魔术方法返回相同的变量两次,导致名称冲突。
class Test { public $foo = 'test'; public function __sleep() { return array("foo", "foo"); // Same value returned twice } } serialize(new Test());
PHP Warning: serialize(): "foo" is returned from __sleep() multiple times
向后兼容性影响
在 PHP 8.0 中,PHP 的默认错误报告级别更改为 E_ALL。除非在自定义 INI 文件中更改了 error_reporting 值,否则除了严重程度的更改之外,这不应该引入任何新错误。
由于严重程度的变化,以前忽略 E_NOTICE 错误的自定义错误处理程序可能会遇到新的 E_WARNING。强烈建议不要调整错误处理程序来忽略这些警告,而是评估警告并纠正无效的错误条件。
一个值得注意的注意事项是,为 PHP 8.1 枚举引入了新的序列化模式。序列化的枚举采用 E:... 格式,并且不能在 PHP 8.1 之前的版本中反序列化。