Hello Again,
I wanted to bring back the topic I started on ArrayObject; I've been doing
a ton of work with ArrayObject lately and finding some odd behavior.
Firstly it would be great to know if these are by design or bugs.
Secondly there are some areas where it likely needs to be improved.
1: ArrayObject return by reference:
Yes, you can tell offsetGet and __get to return by a reference; however, in
the case of multi-dimensional arrays it will not work due to the internal
implementation of ArrayObject. Internally it stores everything in a
private variable "storage" which is an instance of an ArrayObject.
Unfortunately since it is a regular instance of an ArrayObject and not one
of the current declarations it will pose issues when attempting to unset
variables.
Example:
class myArrayObject extends ArrayObject
{
public function &offsetGet($key) {
$var =& $this->storage[$key];
return $var;
}
}
$ao = new myArrayObject(array('foo' => array('bar' => 'baz')));
unset($ao['foo']['bar']);
PHP Notice: Indirect modification of overloaded element of myArrayObject
has no effect
2: ArrayObject and Iterators:
For some reason when you do an exchangeArray with an iterator, it basically
does a type cast leaving you with an array key of the iterator class name
appended with "var". Unfortunately this key is "special" or something
because it cannot be accessed, isset returns false but you can get to your
records by either foreach or shifting or popping the array. Not really
certain if this is intended at all and if so might need to be reworked?
Example:
<?php
class MyIterator implements Iterator
{
private $var = array();
public function __construct($array) {
if (is_array($array)) {
$this->var = $array;
}
}
public function `rewind()` {
reset($this->var);
}
public function `current()` {
return current($this->var);
}
public function `key()` {
return key($this->var);
}
public function `next()` {
return next($this->var);
}
public function valid() {
$key = key($this->var);
$var = ($key !== `NULL` && $key !== FALSE);
return $var;
}
}
$ao = new ArrayObject();
$mi = new MyIterator(array('foo' => 'bar'));
$ao->exchangeArray($mi);
$array = $ao->getArrayCopy();
var_dump($array);
var_dump(isset($array['MyIteratorvar']));
$params = array_shift($array);
var_dump($params);
var_dump(isset($params['foo']));
This will output:
array(1) {
["MyIteratorvar"]=>
array(1) {
["foo"]=>
string(3) "bar"
}
}
bool(false)
array(1) {
["foo"]=>
string(3) "bar"
}
bool(true)
That one had me dumb founded for a while; you can see this behavior just as
easy by doing it directly on the iterator itself and type casting it to an
array.
Example:
$ir = new MyIterator(array('foo' => 'bar'));
var_dump((array) $ir);
Anyhow it would be good to know your thoughts; on these two things. I
believe there is a bug ticket already for the first item; the second item
I didn't see anything within the first few pages but maybe I'm searching
for it without the right keywords.
Thanks for listening!