【问题标题】:What was PHP's "o" serialization format for?PHP 的“o”序列化格式是干什么用的?
【发布时间】:2021-03-25 03:13:46
【问题描述】:

PHP 7.4 的向后不兼容更改列表包含the following note

序列化

o 序列化格式已被移除。由于它从未由 PHP 生成,这可能只会破坏手动制作的字符串的反序列化。

(注意这里指的是 little-o,而不是用于对象序列化的 big-O 格式。)

似乎这不是由 PHP 的 serialize() 函数生成的,但该注释的存在意味着它已被 unserialize() 函数识别。

我已经完成了little test fiddle (3v4l.org),这表明这不仅仅是 big-O 的同义词,这显然是一种可能性。

小提琴通过输出的错误消息中的差异公开了 PHP 中的更改。在 PHP >= 7.4 中,我们在位置 0(遇到 o)处收到错误,而在 7.4 之前,在位置 5(数据所在的位置)报告错误。这意味着o 已被识别,但数据格式错误,这与我在上面已经推断的内容相关。

那么,o 序列化格式是什么,它反序列化为什么,如果 PHP 本身没有实际生成它,为什么它支持这样的功能?

【问题讨论】:

标签: php php-internals language-history


【解决方案1】:

最初,PHP 3 使用o:<num_fields>:{<fields>} 来序列化对象。

以下程序可在 PHP 4.0.0 中运行,可从 php.net/releases/index.php 下载(Windows 二进制文件仍可在 Windows 10 上运行!):

<?php

var_dump(unserialize('o:0:{}'));

输出:

X-Powered-By: PHP/4.0.0
Content-type: text/html

object(stdClass)(0) {
}

我能够将对象序列化格式的原始实现追溯到 1999 年的this commit。 见php3api_var_serialize

那年晚些时候,对象序列化格式为 changed,以包含正在序列化的对象的类名,为 PHP 4 做准备。 本次提交将序列化格式改为o:&lt;classname_length&gt;:"&lt;class_name&gt;":&lt;num_fields&gt;:{&lt;fields&gt;}

这使得 PHP3 和 PHP4 的输出不兼容:PHP4 无法反序列化使用 PHP3 序列化的对象。 因此,another commit was addedo 更改为 O(小写 o 更改为大写 O)。 o 仍然支持 unserialize() 反序列化使用 PHP3 序列化的对象,但 serialize() 不再使用 o

2000年,序列化/反序列化代码was refactored,导致file we see today

可能发生的事情是兼容性层在此过程中的某个地方出现了问题,没有人足够关心 PHP3 的兼容性来修复它。 开头的代码不再适用于过去 15 年发布的任何 PHP 版本。

【讨论】:

  • 这是一个非常有用的答案,它指出了关于 little-o 符号的用途的详细信息。它没有回答问题的“为什么”部分,但也许这已经在时间的迷雾中消失了。我会暂时保留这个问题,但如果没有人能够提供任何进一步的信息,我可能会接受这个作为答案。
  • @HappyDog 在深入了解旧 PHP 代码库后,我更新了答案。仍然不确定我是否回答了你的问题,但现在应该已经结束了:)
  • 哇——有了你的更新,这是一个了不起的答案!如此多的细节,正是我正在寻找的那种历史信息。事实上,它太好了,即使你的答案已经发布,我也要奖励它!
  • 获得赏金。我还在 PHP 迁移说明中添加了一条注释,引用了您的答案:php.net/manual/en/migration74.incompatible.php#125717
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多