(un)serialize()的行为已更改? [英] Changed behavior of (un)serialize()?

查看:106
本文介绍了(un)serialize()的行为已更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是目前为止已记录的php错误: https://bugs.php .net/bug.php?id = 71617 感谢您发现了一个@Danack

Problem is a documented php bug by now: https://bugs.php.net/bug.php?id=71617 thanks to for finding that one @Danack

我只是将应用程序从PHPH 5.5迁移到PHP 7,偶然发现了序列化对象时的一些奇怪行为.

I'm just migrating an application from PHPH 5.5 to PHP 7 and stumbled over some strange behavior when it comes to serializing objects.

我已尝试将其简化为一个最小,完整和可验证的示例,该示例可以在 http:中找到//sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8

I have tried to cook it down to a minimal, complete and verifiable example which can be found at http://sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8

问题是,如果类扩展 ArrayObject ,则所有私有属性似乎如果先serialize()然后再unserialize()该对象消失,

The problem is that if a class extends ArrayObject then all private properties seem to just vanish if you serialize() and then unserialize() that object:

  1. 创建一个具有私有属性的类,并为该属性使用getter/setter方法
  2. 创建该类的对象
  3. 通过设置方法设置私有属性
  4. serialize()对象
  5. unserialize()步骤4的结果
  6. 调用私有属性的getter方法,结果取决于您的PHP版本
    • PHP 5.3-PHP 5.6:结果是在第3步中设置的值
    • PHP 7:结果为空
  1. create a class with a private property and getter/setter method for that property
  2. create an object of that class
  3. set private property via setter method
  4. serialize() object
  5. unserialize() result of step 4
  6. call getter method of private property, result depends on your PHP version
    • PHP 5.3 - PHP 5.6: result is value set in step 3
    • PHP 7: result is null

我尝试将其简化为一个最小,完整和可验证的示例,可以在 http:中找到//sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8 ,您可以在其中使用不同的PHP版本测试代码.

I have tried to cook it down to a minimal, complete and verifiable example which can be found at http://sandbox.onlinephpfunctions.com/code/e926a7398119ea715531cafe4ce6a22c329e53b8 where you can test the code with different PHP versions.

<?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的输出:

Output for PHP 5.6:

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

PHP 7的输出:

demoArrayObject:
public
protected

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

我找不到与serialize()unserialize()ArrayObject类相关的任何已记录的更改,所以我想知道发生了什么.是虫子吗?未记录的功能? ;-)

I could not find any documented changes related to serialize(), unserialize() or the ArrayObject class so I am wondering what's going on. Is it a bug? Undocumented feature? ;-)

由于我们在项目中做了很多serialize()/unserialize()的工作,所以我确实需要确保PHP 7的行为与PHP 5.3+行为100%兼容.

As we do a lot of serialize() / unserialize() in our project I really need to make sure bahavior of PHP 7 is 100% compatible to PHP 5.3+ behavior.

问题:如何使PHP 7表现得像PHP 5.3 + ??

Question: How can I make PHP 7 behave like PHP 5.3+??

推荐答案

尽管此问题已在下一版PHP中修复,但您的代码依赖于未记录的行为这一事实是一个错误,称为"

Although this is fixed for the next release of PHP, the fact that your code is relying on an undocumented behaviour is an error known as "Programming by Coincidence". From the fine article:

如何巧合编程

假设给Fred编程任务.弗雷德(Fred)输入一些代码,然后尝试一下,它似乎可以工作.弗雷德(Fred)输入了更多代码,尝试了一下,但它似乎仍然有效.经过数周的这种编码方式后,程序突然停止运行,经过数小时的尝试修复后,他仍然不知道为什么.弗雷德可能会花费大量时间来追踪这段代码,而无法对其进行修复.无论他做什么,似乎都行不通.

How to Program by Coincidence

Suppose Fred is given a programming assignment. Fred types in some code, tries it, and it seems to work. Fred types in some more code, tries it, and it still seems to work. After several weeks of coding this way, the program suddenly stops working, and after hours of trying to fix it, he still doesn’t know why. Fred may well spend a significant amount of time chasing this piece of code around without ever being able to fix it. No matter what he does, it just doesn’t ever seem to work right.

发生实现只是因为当前编写代码的方式而发生.您最终将依赖未记录的错误或边界条件.

Accidents of implementation are things that happen simply because that’s the way the code is currently written. You end up relying on undocumented error or boundary conditions.

在这种情况下,不能保证在扩展ArrayObject时,子类的值将正确地反序列化.

In this case, there is no guarantee that when you extend ArrayObject the values of the child class will be unserialized correctly.

使用组合而不是继承会更安全,或者在子方法上编写序列化/反序列化方法将使您能够控制序列化/反序列化.另外,不使用序列化/反序列化,而是使用自己的接口也比魔术"内部方法更具可预测性.

Either using composition rather than inheritance would be much safer, or writing serialize/unserialize methods on the child method would allow you to control the serialization/deserialization. Alternatively, just not using serialize/unserialize and instead using your own interface can also be more predictable than the "magic" internal methods.

这篇关于(un)serialize()的行为已更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆