PHP 8.3: unserialize() обновление ошибки E_NOTICE до E_WARNING
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 Notice: unserialize(): Error at offset 0 of 14 bytes
+ PHP Warning: unserialize(): Error at offset 0 of 14 bytes
В идеале невозможность десериализации данной строки должна быть серьёзной ошибкой и вызывать исключение. Однако, для обеспечения обратной совместимости и упрощения обновления в PHP 8.3 увеличили уровень ошибки, а в будущем возможно его обновления до вызова исключения.
Несоответствие условий ошибки
Не все ошибки
unserialize()
вызывалиE_NOTICE
. Например десериализация строки, которая превышаем максимальный предел глубины (настроенная INI- параметромunserialize_max_depth
, начиная с PHP 7.4 ), уже выдаётE_WARNING
. В этом случае продолжает выдаватьсяE_WARNING
без изменений.
Затрагиваемые условия ошибки
Следующие три условия, которые ранее выдавали E_NOTICE
, изменены на E_WARNING
, начиная с PHP 8.3:
- Синтаксические ошибки (иногда вызванные неправильными обработчиками сериализации) в переданной строке
unserialize('invalid string');
- PHP Notice: unserialize(): Error at offset 0 of 12 bytes
+ PHP Warning: unserialize(): Error at offset 0 of 12 bytes
- Сбои в пользовательских обработчиках десериализации с использованием магического метода
__unserialize
, например метод__unserialize()
не возвращает ни какого значения
class Test {
public function __unserialize(array $data) { } // Ничего не возвращает
}
- PHP Notice: unserialize(): Unexpected end of serialized data
+ PHP Warning: unserialize(): Unexpected end of serialized data
- Дважды возвращает одну и туже переменную из магического метода
__sleep()
, вызывая конфликт имён
class Test {
public $foo = 'test';
public function __sleep() {
return array("foo", "foo"); // Дважды возвращается одно и то же значение
}
}
serialize(new Test());
- PHP Notice: serialize(): "foo" is returned from __sleep() multiple times
+ PHP Warning: serialize(): "foo" is returned from __sleep() multiple times
Влияние обратной совместимости
В PHP 8.0 уровень сообщений об ошибках PHP по умолчанию был изменён на E_ALL
. Если значение error_reporting
не было изменено в пользовательском INI-файле, это не должно привести к возникновению каких-либо новых ошибок, кроме изменения уровня серьёзности.
Пользовательские обработчики ошибок, которые ранее игнорировали ошибки E_NOTICE
, могут столкнуться с новым E_WARNING
из-за изменения серьёзности. Вместо того, чтобы настраивать обработчики ошибок для игнорирования этих предупреждений, настоятельно рекомендуется оценить предупреждение и исправить недопустимое состояние ошибки.
Одно важно предостережение заключается в том, что новый шаблон сериализации включает представленные в PHP 8.1 Перечисления (Enums
). Сериализованные перечисления принимают формат E:...
и не могут быть десериализованы в версиях PHP до PHP 8.1.