Originally I was thinking this was going to be a piece of cake.. not for me..
I am trying to extend the offsetGet() function to return null if the item is not in the ArrayObject. So far I can not seem to get it working without errors.
php -v: 5.3.29
What am I doing wrong? Below is my code and the error:
My extended ArrayObject class:
class IssetArray extends \ArrayObject {
public function &offsetGet($offset) {
$var = $this->offsetExists($offset) ? parent::offsetGet($offset) : null;
return $var;
}
}
Here is how I am calling it:
$array = new \IssetArray();
$array['item'] = 123;
var_dump($array['item']);
var_dump($array['something']['noItem']);
$array['something']['foo'] = 'bar';
var_dump($array['something']['foo']);
$normalArrayObject = new \ArrayObject();
$normalArrayObject['something']['foo'] = 'bar';
var_dump($normalArrayObject['something']['foo']);
var_dump($normalArrayObject['something']['noItem']);
Outputs:
int(123)
NULL
Notice: Indirect modification of overloaded element of \IssetArray has no effect in -- on line --
NULL
string(3) "bar"
Notice: Undefined index: noItem in -- on line --
NULL
What am I doing wrong?? If I call the normal ArrayObject I don't get the indirect modification error. I am so confused at this point.
Any help would be wonderful. I have googled and googled with no luck.
Update -----------
When trying to do the same thing with ArrayAccess I run into the same issue. How can I get around this with ArrayAccess?
My implementation:
class IssetArray implements \ArrayAccess {
private $container = array();
public function __construct() {}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function &offsetGet($offset) {
$var = isset($this->container[$offset]) ? $this->container[$offset] : null;
return $var;
}
}
This results in the same issue I am seeing with ArrayObject. Notice: Indirect modification of overloaded element of \IssetArray has no effect in -- on line --
Short answer: this is a nasty side effect of overloading the offsetGet()
method from ArrayObject
.
$array['something']['foo'] = 'bar';
As part of the assignment, ArrayObject::offsetGet('something')
is called and the return value is expected to return a reference; the problem is that, despite the definition of &offsetGet()
, it doesn't in fact return a reference.
What you're really returning is a temporary variable and therefore the notice is correct to assert that any changes made on that variable will not be reflected in the final array.
Btw, this doesn't happen if you implement ArrayAccess
instead; of course, you won't get all the methods that come with ArrayObject
either :(
It seems from this report that HHVM exhibits the correct behaviour and PHP 7 will not generate any notices (but has the wrong behaviour during assignment).