When programming with Javascript I like the fact that an array is an object, so much, that I created similar array type of object in PHP. PHP is branded to be dynamic language, in this post I test how dynamic the language can be by creating Javascript-like arrayobject. I created a class which extends ArrayObject class. ArrayObject gives ability to objects to act as array (they can go through foreach etc). With magic methods, I was able to implement all array_* functions as methods for arrayobject.
class Arr extends ArrayObject {
private $container=array();
public function __construct($arr) {
parent::__construct($arr);
$this->container=$arr;
}
public function getContainer() {
return $this->container;
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
parent::offsetSet($offset, $value);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
parent::offsetUnset($offset);
}
public function __call($name, $args) {
if(function_exists('array_'.$name)) {
foreach($args as $key=> $ar) {
if(is_object($ar) && get_class($ar)=='Arr')
$args[$key]=$ar->getContainer();
}
set_error_handler(function($a,$b,$c,$d) {throw new Exception($b);});
try {
$ref=new ReflectionFunction('array_'.$name);
if(current($ref->getParameters())->isPassedByReference()) //walk
$newargs=array(&$this->container);
else
$newargs=array((array)$this);
foreach($args as $arg) {
$newargs[]=$arg;
}
$r=call_user_func_array('array_'.$name,$newargs);
} catch (Exception $e) {
array_splice( $args, 2, 0, array((array)$this));
$r=call_user_func_array('array_'.$name,$args);
}
restore_error_handler();
if(is_array($r))
return new Arr($r);
return $r;
}
}
}
private $container=array();
public function __construct($arr) {
parent::__construct($arr);
$this->container=$arr;
}
public function getContainer() {
return $this->container;
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
parent::offsetSet($offset, $value);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
parent::offsetUnset($offset);
}
public function __call($name, $args) {
if(function_exists('array_'.$name)) {
foreach($args as $key=> $ar) {
if(is_object($ar) && get_class($ar)=='Arr')
$args[$key]=$ar->getContainer();
}
set_error_handler(function($a,$b,$c,$d) {throw new Exception($b);});
try {
$ref=new ReflectionFunction('array_'.$name);
if(current($ref->getParameters())->isPassedByReference()) //walk
$newargs=array(&$this->container);
else
$newargs=array((array)$this);
foreach($args as $arg) {
$newargs[]=$arg;
}
$r=call_user_func_array('array_'.$name,$newargs);
} catch (Exception $e) {
array_splice( $args, 2, 0, array((array)$this));
$r=call_user_func_array('array_'.$name,$args);
}
restore_error_handler();
if(is_array($r))
return new Arr($r);
return $r;
}
}
}
To use the class, all we need to do is wrap an array with Arr class:
$fruits = new Arr(array("lemon", "orange", "banana", "apple"));
Now we have $fruits arrayobject, which have all "array_*" functions as method. There are over seventy array_* functions which we can now use as method. Lets see how to use it:
$fruits->change_key_case(CASE_UPPER)->filter()->walk(function($value,$key) {
echo $key.': '.$value."\r\n";
});
echo $key.': '.$value."\r\n";
});
In example above, all keys in $fruits array are changed to uppercase, then empty members are filtered out, finally a function is applied to all members of an array. Now lets compare how same would be done with native array
array_walk(array_filter(array_change_key_case($fruits)),function($value,$key) {
echo $key.': '.$value."\r\n";
})
echo $key.': '.$value."\r\n";
})
This seems rather interesting, as 49 lines of code change the way and idea how PHP code can be written. PHP is dynamic language after all.
Ei kommentteja:
Lähetä kommentti