PHP对象与整型变量

6

我注意到PHP对象的一些奇怪行为,并且找不到相关的文档解释。

以下代码演示了这种行为

<?php
$a = (object) array( 0 => 1 );
foreach($a as $b => $c) {
  $a->$b = ++$c;  //I'm expecting the key to be overwritten here
}
var_dump($a);
$var = 0;
var_dump($a->$var);
$var = "0";
var_dump($a->$var);

以及输出结果

object(stdClass)#1 (2) {
  [0]=>
  int(1)
  ["0"]=>
  int(2)
}
int(2)
int(2)

在使用 -> 语法时,类的数字部分是否不可访问?


作为答案。是的,使用->无法访问它。但是为什么和如何做到的,我不知道,好问题! - Chilion
这里的key to be overwritten here将被覆盖,你是否想要使用$a->1而不是$a->0 - Ronser
我希望$a只包含一个变量,而不是两个。 - exussum
2个回答

5
当您对数组执行 (object) 强制转换时,您会将该数组提升为匿名对象(即 stdClass)的 internal 属性列表。
对象属性的索引方式与数组略有不同,具体而言,对象属性名始终被视为字符串,而数组索引则根据预期类型查找(例如,数字字符串被视为整数)。
上述行为不影响 foreach 循环,因为在这里没有哈希操作;就 PHP 而言,正在迭代常规数组。
回答您的问题,是的,无法使用 -> 运算符访问原始数组中的数字键。为避免此问题,应在执行强制转换之前从数组中删除数字索引。
很难在文档中找到此行为,但可以在 此处 找到一些提示:

如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名称,其中有一些值得注意的例外情况:整数属性无法访问...

FYI

在这种情况下,您可以通过使用引用来规避问题;但不建议这样做,请遵循早期的建议,不要使用数字属性名称:
foreach ($a as &$c) {
    ++$c;
}
unset($c);

更新

2014年11月26日:我已经更新了文档;实时页面将在本周五更新 - commit


为什么强制类型转换不会重新索引属性为字符串?这有文档记录吗? - exussum
var_dump((array) ((object) array( 0 => 1 ))); 显示了文档中不应该显示的项目。 - exussum
它说键已经丢失,即使文档建议不应该这样做,但 $a = (array) $a; echo $a[0] 仍然有效。 - exussum
我不太确定,因为如果没有进行初始转换,似乎无法使数字属性? - exussum
但这仍然意味着文档是不正确的,这会导致一个字符串键“5”可访问。 - exussum
显示剩余5条评论

1

stdClass 处理数据非常宽松,因为它是一个内部数组的对象表示形式(因此可以轻松进行强制类型转换)。

$stdClassObject->property = "value";

该属性被处理为字符串,但转换后,属性类型不会改变(这在某种程度上是可以理解的,因为如果您将其转换为对象,然后再次转换为数组,您将失去所有整数索引)。
我认为他们做得已经很好了,但是您可以创建自己的stdClass替代品 :-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接