note 89621 deleted from class.arrayobject by danbrown
| From: | danbrown@php.net | Date: | Tue, 17 Mar 2009 13:18:58 +0000 |
| Subject: | note 89621 deleted from class.arrayobject by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-152026@lists.php.net to get a copy of this message | ||
Note Submitter: rarioj at gmail dot com
----
For those who thinks that it is impossible for a class implementing ArrayAccess to behave exactly
like a real array, I wrote this class for my homemade framework. It features:
* It's an object so you can perform chained gets/sets:
$data->fruit->color->red = 'Apple';
* It's an array so you can perform multidimensional gets/sets too:
$data['fruit']['color']['red'] = 'Apple'; //identical as the
above code
* Returns value by reference;
$tmp =& $data['fruit'];
$tmp->color->red = 'Apple'; // or...
$tmp['color']['red'] = 'Apple';
* Use array functions. The method &toArray, returns the reference of the actual array contained
in the object. This is very fast even for a big array, since whatever stored in Data object is the
actual array.
array_walk_recursive($data->toArray(), 'someCallback');
<?php
/** Comments are trimmed down...
* Kiara Framework 090312 -alpha-
* @author Ario <rarioj at gmail dot com>
* @license BSD License
*/
class Data implements Countable, Iterator, ArrayAccess
{
protected $_data;
protected $_pos;
public function __construct(array $array = array())
{
$this->_data =& $array;
$this->_pos = 0;
}
public function __get($key)
{
if (!isset($this->_data[$key])) $this->_data[$key] = array();
return $this->objectify($this->_data[$key]);
}
public function __set($key, $value) { $this->_data[$key] = $value; }
public function __isset($key) { return isset($this->_data[$key]); }
public function __unset($key) { unset($this->_data[$key]); }
public function count() { return count($this->_data); }
public function current() { return $this->objectify(current($this->_data)); }
public function key() { return key($this->_data); }
public function next() { next($this->_data); $this->_pos++; }
public function rewind() { reset($this->_data); $this->_pos = 0; }
public function valid() { return $this->_pos < count($this->_data); }
public function offsetGet($offset)
{
$data =& $this->_data;
if (is_null($offset)) {
$data[] = array();
end($data);
$offset = key($data);
}
return $this->__get($offset);
}
public function offsetSet($offset, $value) { $this->__set($offset, $value); }
public function offsetExists($offset) { return $this->__isset($offset); }
public function offsetUnset($offset) { $this->__unset($offset); }
public function &toArray() { return $this->_data; }
public function objectify(&$data)
{
if (!is_array($data)) return $data;
return new self(&$data);
}
}
?>
<?php
// Constructing the class, you could provide the initial array as a param.
$data = new Data( /* put initial array here */ );
// Since this object behave like an object, and an array:
// You can do chained sets:
$data->one->two->three = '123';
// And also assign using multidimensional matrix:
$data['four']['five']['six'] = '456';
// You can also return the object as a reference.
$tmp =& $data['seven'];
// The do the stuff with it.
$tmp['eight']['nine']['ten'] = '78910';
$tmp->eight->nine->eleven = '78911';
// Test: A function to double a value.
function _double(&$v) {
$v = (int) $v * 2;
}
// Test: A function to print key => value pair.
function _print($v, $k) {
echo $k.' = '.$v.PHP_EOL;
}
// Double the value.
array_walk_recursive($data->toArray(), '_double');
// Print them.
array_walk_recursive($data->toArray(), '_print');
// See what we have now.
print_r($data->toArray());
?>
Result:
three = 246
six = 912
ten = 157820
eleven = 157822
Array
(
[one] => Array
(
[two] => Array
(
[three] => 246
)
)
[four] => Array
(
[five] => Array
(
[six] => 912
)
)
[seven] => Array
(
[eight] => Array
(
[nine] => Array
(
[ten] => 157820
[eleven] => 157822
)
)
)
)