这是PHP错误还是功能?

时间:2014-05-22 21:40:34

标签: php oop

我有两个脚本及其输出:

第一个脚本

class A {
  public $view = "foo";

  public function getView()
  {
      return $this->view;
  }
}

$a = new A();
$b = serialize($a);
file_put_contents("/tmp/test.tmp",$b);
var_dump($b);

及其输出:

object(A)[1]
  public 'view' => string 'foo' (length=3)

string 'O:1:"A":1:{s:4:"view";s:3:"foo";}' (length=33)

比我跑:

第二个脚本

class A {
   private $view = "bar";

   public function getView()
   {
       return $this->view;
   }
}

$a = unserialize(file_get_contents("/tmp/test.tmp"));

var_dump($a, $a->getView());

并显示:

object(A)[1]
  private 'view' => string 'bar' (length=3)
  public 'view' => string 'foo' (length=3)

string 'bar' (length=3)

正如您所看到的,唯一的变化是公共$ view变为私有。

我的同事彼得发现了这个,心里一阵:) :)

编辑:

我相信如果你将一些对象(例如通过Doctrine)序列化到DB,这可能真的有问题,而不是更新代码库而不更新存储在DB中的数据(这将成为 - 正如我所假设的 - 解析对象序列化为文本和更新他们使用一些迁移脚本)然后反序列化数据并对其进行处理。我认为这并不罕见,而且这种行为可能是不受控制的。如果未序列化的对象类定义与实际的不同,我很乐意看到PHP抛出错误/异常等。

2 个答案:

答案 0 :(得分:4)

它都不是。使用unserialize表示类的对象的序列化数据,其定义与unserialize调用环境已知的类定义不同,在PHP文档中根本没有定义。因此,它不是官方功能。但由于没有定义行为和结果,结果也不能被认为是一个错误。

但是如果你真的想把它分成两个类别中的一个" bug"或者"功能",您可能会将其称为未记录的功能,因为它似乎不会使PHP进入PHP脚本执行被破坏的状态"。 (虽然我不会在未来的版本中依赖这种行为 - 但这是一个不同的故事。)

答案 1 :(得分:1)

你可以更快地得到奇怪的结果(demo):

var_dump(unserialize("O:8:\"stdClass\":3:{s:4:\"\0*\0p\";N;s:11:\"\0stdClass\0p\";N;s:1:\"p\";N;}"));

//class stdClass#1 (3) {
//  protected $p =>
//  NULL
//  private $p =>
//  NULL
//  public $p =>
//  NULL
//}

\0 - 0字节字符

这不是一个错误:https://bugs.php.net/bug.php?id=51173

  

修复此问题会产生更多问题,例如性能下降   解决的问题。

文档可能包含一些关于它的文字,但事实并非如此。