6

我从PHP 手册中读到了这个:

如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名称,有一些值得注意的例外:整数属性是不可访问的;私有变量在变量名前面加上类名;受保护的变量在变量名前有一个“*”。这些前置值在两边都有空字节。 这可能会导致一些意外行为:

class A {
    private $A; // This will become '\0A\0A' }

class B extends A {
    private $A; // This will become '\0B\0A'
    public $AA; // This will become 'AA' }

var_dump((array) new B()); 

上面似乎有两个名为“AA”的键,尽管其中一个 实际上名为“\0A\0A”。

我不太明白那些字体像这样的部分的含义。

什么是整数属性?

“这些前置值在任一侧都有空字节。这可能导致一些意外行为”是什么意思?

和“什么意思?上面看起来有两个名为'AA'的键,尽管其中一个实际上名为'\0A\0A'”

4

2 回答 2

4

通过使用此代码,您可以深入了解新的数组键。

$x = (array)new B();

foreach ($x as $key => $value) {
    echo bin2hex($key), ' = ', $value, PHP_EOL;
}

它显示了键值的十六进制表示,从中您可以更清楚地看到发生了什么:

00420041 = 
4141 = 
00410041 = 

第一个属性 ( B::A) 的数组键被编码为"\x00B\x00A", ie chr(0) . 'B' . chr(0) . 'A',因为它的可见性是私有的B

第二个属性 ( B::AA) 被编码为 simple 'AA',因为它的可见性是公开的。

第三个属性 ( A::A) 与第一个非常相似,被编码为"\x00A\x00A",因为它的可见性对 是私有的A

我不完全确定整数属性是什么。我不会担心数值属性,因为它们的使用可以忽略不计并且不鼓励(这可能是为什么没有太多提及这个“功能”的原因。

于 2013-01-27T12:21:01.533 回答
4

整数属性

这指的是名称是十进制整数的字符串表示形式的属性。例如:

$o = new stdClass;
$o->{"123"} = 'foo';        // create a new integer property

echo $o->{"123"}, PHP_EOL;  // verify it's there

$a = (array)$o;             // convert to array

echo $a['123'];             // OOPS! E_NOTICE: Undefined offset!

var_dump(array_keys($a));   // even though the key appears to be there!
print_r($a);                // the value appears to be there too!

一般来说,如果你重视你的理智,PHP 中的整数属性不是你应该接近的东西。

前置值由null

对于privateprotected属性,生成的数组键将包含不可打印字符"\0"。这可能很有用(因为该字符对于属性名称是不合法的,您可以使用此信息来确定属性的可见性),但如果您不希望它存在,它也可能是一个麻烦。例子:

class A {
    private $A; // This will become '\0A\0A'
}

class B extends A {
    private $A; // This will become '\0B\0A'
    public $AA; // This will become 'AA'
}

$a = (array) new B();

// The array appears to have the keys "BA", "AA" and "AA" (twice!)
print_r(array_keys($a));

// But in reality, the 1st and 3rd keys contain NULL bytes:
print_r(array_map('bin2hex', array_keys($a)));

您可以从数组键中提取可见性信息,如下所示:

$a = (array) new B();
foreach ($a as $k => $v) {
    $parts = explode(chr(0), $k);
    if (count($parts) == 1) {
        echo 'public $'.$parts[0].PHP_EOL;
    }
    else if ($parts[1] == "*") {
        echo 'protected $'.$parts[2].PHP_EOL;
    }
    else {
        echo 'private '.$parts[1].'::$'.$parts[2].PHP_EOL;
    }
}
于 2013-01-27T12:44:53.607 回答