在PHP中,unset()调用在什么条件下重置数组索引?

时间:2010-08-06 08:11:40

标签: php

unset函数与SimpleXML解码数组结合使用时,我发现了一个奇怪的问题。应用于此类数组的索引之一(数字索引)的unset函数似乎重置了数组索引。

这对我来说似乎是一种无证的行为(或者更像是一个错误)。有没有人得到解释为什么对SimpleXML阵列进行“特殊的重建索引”处理?

这是一个解释它的测试用例。

<?php
$a = array( 1, 2, 3, 4 );
echo "Regular array, before unset(\$a[1]): " . print_r( $a, 1 );
unset( $a[1] );
echo "Regular array, after unset(\$a[1]): " . print_r( $a, 1 );

$xml = simplexml_load_string( <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node>1</node>
<node>2</node>
<node>3</node>
<node>4</node>
<node>5</node>
</root>
EOT
 );

echo "SimpleXML array, before unset(\$a[1]): " . print_r( $xml, 1 );
unset( $xml->node[1] );
echo "SimpleXML array, after unset(\$a[1]): " . print_r( $xml, 1 );

我得到的输出是,

Regular array, before unset($a[1]): Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)
Regular array, after unset($a[1]): Array
(
    [0] => 1
    [2] => 3
    [3] => 4
)
SimpleXML array, before unset($a[1]): SimpleXMLElement Object
(
    [node] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
            [4] => 5
        )

)
SimpleXML array, after unset($a[1]): SimpleXMLElement Object
(
    [node] => Array
        (
            [0] => 1
            [1] => 3
            [2] => 4
            [3] => 5
        )

)

3 个答案:

答案 0 :(得分:2)

如果数组实际上是一个对象而不是一个简单的数组,并且该类有一个魔术__unset()方法定义,那么脚本编写者可能会选择故意重新索引元素,以便键保持顺序...有益于那些喜欢使用for($i = 0; $i < count($nodes); $i++)而不是foreach($nodes as $node)循环“数组”的程序员。

我认为SimpleXML是用C而不是PHP编写的,但是同样的原则可能已用于防止for($i = 0; $i < count($nodes); $i++)编码器使用时出现“破坏”。

答案 1 :(得分:2)

原因是访问$xml->node并不能提供实际数组。 $xml->node[1]返回一个SimpleXMLElement实例,它有一个魔术方法__unset,当你取消它时会调用它。它不使用PHP的默认未设置行为,因为它对数组使用。

答案 2 :(得分:0)

在您的代码中

unset( $xml->node[1] );

unset($a[1])
就像你在输出中描述的那样。

你做的unset( $xml->node[1] );将是:

unset($a[node][1])

因此它是正确的。