Intereting Posts
Вызов функции-члена где () на не-объекте Laravel 4.2 php URL – заменить знак вопроса и параметр слэш Как захватить содержимое Facebook Note с помощью Graph API? file_get_contents ( 'PHP: // ввод'); с приложением / x-www-form-urlencoded; Командная строка Yii не поддерживает модели автозагрузки Сообщение. Для этого адаптера требуется расширение PDO, но расширение не загружено. jQuery Проверять использование удаленного метода для проверки того, существует ли имя пользователя Время истечения срока действия изображения Пользователь загружает структуру папок Получайте и обновляйте текст каждые несколько секунд от источника HTTP до HTTPS-сайта Как отображать ошибки исключения, создаваемые платформой Zend получить уникальное значение из массива и итоговых сумм PHP – Уничтожьте сеанс, если нет никаких действий за 10 минут Вызовите скрипт PHP со страницы JSP и покажите его вывод на странице JSP Использование $ this, если не в объектном контексте – Laravel 4 PHP 5.4.12

Изменено поведение (un) serialize ()?

EDIT: Проблема – это зарегистрированная ошибка php: https://bugs.php.net/bug.php?id=71617 благодаря обнаружению того, что один @Danack

Я просто переношу приложение из PHPH 5.5 на PHP 7 и наткнулся на какое-то странное поведение, когда дело доходит до сериализации объектов.

Я попытался подготовить его к минимальному, полному и проверенному примеру, который можно найти по адресу http://sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8

Проблема в том, что если класс расширяет ArrayObject, то все частные свойства, похоже, просто исчезают, если вы serialize() а затем unserialize() этот объект:

  1. создать класс с частной собственностью и метод getter / setter для этого свойства
  2. создать объект этого класса
  3. установить частную собственность через метод setter
  4. serialize() объект
  5. unserialize() результат шага 4
  6. call getter метод частной собственности, результат зависит от вашей версии PHP
    • PHP 5.3 – PHP 5.6: результат – значение, заданное на шаге 3
    • PHP 7: результат равен нулю

Я попытался свести его к минимальному, полному и проверенному примеру, который можно найти по адресу http://sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8, где вы можете протестировать код с разными версиями PHP.

 <?php class demoStdObject { public $public = ''; protected $protected = ''; private $private = ''; public function getPublic() { return $this->public; } public function getProtected() { return $this->protected; } public function getPrivate() { return $this->private; } public function setPublic($public) { $this->public = $public; } public function setProtected($protected) { $this->protected = $protected; } public function setPrivate($private) { $this->private = $private; } } class demoArrayObject extends ArrayObject { public $public = ''; protected $protected = ''; private $private = ''; public function getPublic() { return $this->public; } public function getProtected() { return $this->protected; } public function getPrivate() { return $this->private; } public function setPublic($public) { $this->public = $public; } public function setProtected($protected) { $this->protected = $protected; } public function setPrivate($private) { $this->private = $private; } } $arrayObject = new demoArrayObject(); $stdObject = new demoStdObject(); testSerialize($arrayObject); echo str_repeat('-',30) . "\n"; testSerialize($stdObject); function testSerialize($object) { $object->setPublic('public'); $object->setProtected('protected'); $object->setPrivate('private'); $serialized = serialize($object); $unserialized = unserialize($serialized); echo get_class($object) . ":\n"; echo $unserialized->getPublic() . "\n"; echo $unserialized->getProtected() . "\n"; echo $unserialized->getPrivate() . "\n"; } 

Выход для PHP 5.6:

 demoArrayObject: public protected private ------------------------------ demoStdObject: public protected private 

Выход для PHP 7:

 demoArrayObject: public protected ------------------------------ demoStdObject: public protected private 

Я не смог найти никаких документированных изменений, связанных с serialize() , unserialize() или классом ArrayObject поэтому мне интересно, что происходит. Это ошибка? Недокументированная функция? 😉

Поскольку мы делаем много serialize() / unserialize() в нашем проекте, мне действительно нужно убедиться, что bahavior PHP 7 на 100% совместим с поведением PHP 5.3+.

Вопрос: Как я могу заставить PHP 7 вести себя как PHP 5.3+?

Хотя это исправлено для следующего выпуска PHP, тот факт, что ваш код полагается на недокументированное поведение, является ошибкой, известной как « Программирование путем совпадения ». Из прекрасной статьи:

Как программировать путем совпадения

Предположим, что Fred задано программирование. Фред в каком-то коде, пытается, и, похоже, работает. Фред использует еще один код, пытается его, и он все еще работает. После нескольких недель кодирования таким образом, программа внезапно перестает работать, и после нескольких часов попытки исправить это он все еще не знает, почему. Фред вполне может потратить значительное количество времени на то, чтобы преследовать этот кусок кода, не имея возможности его исправить. Независимо от того, что он делает, он просто никогда не работает правильно.

Несчастные случаи

Несчастные случаи реализации – это вещи, которые происходят просто потому, что именно так написан код. В конечном итоге вы полагаетесь на недокументированную ошибку или граничные условия.

В этом случае нет гарантии, что при расширении массива ArrayObject значения дочернего класса будут корректно неэтериализованы.

Либо использование композиции, а не наследование было бы намного более безопасным, или писать методы сериализации / несериализации по дочернему методу позволяли бы управлять сериализацией / десериализацией. В качестве альтернативы, просто не используя сериализацию / несериализацию и вместо этого используя свой собственный интерфейс, также может быть более предсказуемым, чем «магические» внутренние методы.