Reputation: 537
I've found a strange issue when using unset
function in combination with a SimpleXML decoded array. The unset
function applied on one of the index of such an array (which is numeric-indexed), seems to reset the array index.
This seems like an undocumented behavior to me (or more like a bug). Has anyone got an explanation why there's a "special reindexing" treatment for SimpleXML arrays?
Here's a test case that explains it.
<?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 );
The output that I get is,
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
)
)
Upvotes: 2
Views: 324
Reputation: 56430
The reason is that accessing $xml->node
does not give you an actual array. $xml->node[1]
returns you an instance of SimpleXMLElement, which has a magic method __unset
that is called when you unset it. It doesn't use the PHP's default unset behavior as it does for the array.
Upvotes: 2
Reputation: 212412
If the array is actually an object rather than a simple array, and the class has a magic __unset() method defined, then the scripters may have choose to deliberately reindex the elements so that the keys remain sequential... beneficial for those coders who like looping through 'arrays' using for($i = 0; $i < count($nodes); $i++)
rather than foreach($nodes as $node)
.
I imagine that SimpleXML is written in C rather than PHP, but the same principle may have been applied to prevent "breakages" when being used by the for($i = 0; $i < count($nodes); $i++)
coders.
Upvotes: 2
Reputation: 7213
In your code you do
unset( $xml->node[1] );
not
unset($a[1])
like you describe in your output.
The unset( $xml->node[1] );
you do, would be:
unset($a[node][1])
And therefore it is correct.
Upvotes: 0