功能实现有时会在不同版本之间发生变化,这并不奇怪,但不是这样......看看:
$array = ["abc","def"];
$object = new stdclass();
foreach($array as $index => $value) {
$object->$index = $value;
}
var_dump(get_object_vars($object));
对于5.6.x,然后是我们得到7.0.17和7.1.3:
array(2) {
[0]=> string(3) "abc"
[1]=> string(3) "def"
}
但是对于7.0.0和7.0.16以及7.1.0,我们得到:
array(2) {
["0"]=> string(3) "abc"
["1"]=> string(3) "def"
}
请参阅?键是整数或字符串,具体取决于版本。
为什么呢?这些变化背后的原因是什么?为什么在任何地方都没有记录这个?或者......是吗?
答案 0 :(得分:1)
如果你仔细观察3v4.org输出上的版本,它在7.0.0中被破坏,包括7.0.16和7.1.0,包括7.1.2。因此,这是7.0中引入的错误,并在7.0.17和7.1.3(均于2017年3月16日发布)中及时修复了两个活动版本。
查看the PHP changelog,我们可以看到相关的相关条目:
修正了错误#73998(array_key_exists在get_object_vars创建的数组上失败)。
这会引导我们the bug tracker,从那里到commit dd9cf23457e21d2bda29dc92d437b9dbd14027b2 in th git repo:
BUG#73998:无法从get_object_vars
访问数字属性
该修复包括添加一个检查是否存在数字键,如果有,则跳过标有“fast_copy”的块。
因此,这是在PHP 7开发过程中进行的性能优化的不良副作用,现在已在所有受支持的版本中得到修复。
有趣的是,Andrea在错误报告中评论说它与描述一般问题的an RFC to change the behaviour of object-to-array casts密切相关:
因为数组和对象对底层的HashTable类型有不同的限制,它们可以拥有什么类型的密钥,Zend引擎必须在HashTables之上的层上强制执行它们的限制,在实现数组和对象本身的代码中。这意味着如果绕过该代码并直接修改底层HashTable,则数组和对象可能存在无效的内部状态。
RFC解决的具体案例:
例如,$ arr = [0 => 1,1 => 2,2 => 3]; $ obj =(object)$ arr;生成一个名为1和2的不可访问属性的对象,而$ obj = new stdClass; $ obj-> {'0'} = 1; $ obj-> {'1'} = 2; $ obj-> {'2'} = 3;生成一个具有不可访问键“0”,“1”和“2”的数组。使用get_object_vars()时也会出现同样的问题。
RFC在7.2.0中实现,因为它改变了记录的行为,但get_object_vars()
的行为实际上是7.0中的无意更改,因此实现为错误修复。
答案 1 :(得分:0)
实际上这是一个错误,因为变量必须以字母开头。
变量名遵循与PHP中其他标签相同的规则。一个有效的 变量名以字母或下划线开头,后跟任意名称 字母,数字或下划线的数量。作为正则表达式, 它将被表达为:'[a-zA-Z_ \ x7f- \ xff] [a-zA-Z0-9_ \ x7f- \ xff] *'
http://php.net/manual/en/language.variables.basics.php
因此,当您尝试设置变量$object->$index = $value;
时,它必须抛出错误(您无法设置变量,如$1 = 'foo';
或$obj->1 = 'foo';
)。
array(2) {
["0"]=> string(3) "abc"
["1"]=> string(3) "def"
}
是正确的结果,因为get_object_vars
返回关联数组。
返回值¶
返回定义的对象可访问非静态的关联数组 范围中指定对象的属性。如果房产没有 如果已赋值,则返回NULL值。