Best solution for "Array chaining"
For my project I wrote a small config class that loads its data from a .ini file. It overwrites the magic __get() method in order to provide simplified access to the (read only) config values.
Example config.ini.php:
;<?php exit; ?>
[General]
auth = 1
user = "halfdan"
[Database]
host = "127.0.0.1"
My config class (singleton pattern - simplified here) looks like this:
class Config {
protected $config = array();
protected function __construct($file) {
// Preserve sections
$this->config = parse_ini_file($file, TRUE);
}
public function __get($name) {
return $this->config[$name];
}
}
Loading the config would create an array structure like this:
array(
"General" => array(
"auth" => 1,
"user" => "halfdan"
),
"Database" => array(
"host" => "127.0.0.1"
)
)
It's possible to access the first level of the array by doing Config::getInstance()->General
, and the values using Config::getInstance()->General['user']
. What I really want though is being able to access all configuration variables by doing Config::getInstance()->General->user
(syntactic sugar). The array is not an object and the "->" isn't defined on it, so this simply fails.
I thought of a solution and would like to get some public opinion about it:
class Config {
[..]
public function __get($name) {
if(is_array($this->config[$name])) {
return new ConfigArray($this->config[$name]);
} else {
return $this->config[$name];
}
}
}
class ConfigArray {
protected $config;
public function __construct($array) {
$this->config = $array;
}
public function __get($name) {
if(is_array($this->config[$name])) {
return new ConfigArray($this->config[$name]);
} else {
return $this->config[$name];
}
}
}
This would all开发者_开发问答ow me to chain my configuration access. As I'm using PHP 5.3 it might also be a good idea to let ConfigArray extend ArrayObject (SPL is activated per default in 5.3).
Any suggestions, improvements, comments?
If the elements of your $this->config
array are also instances of your Config
class, then it works.
The Zend Framework has a similar component they call Zend_Config. You can download the source and examine how they implemented it. They didn't have to go all the way to extending ArrayObject
.
The Zend_Registry class has similar usage and it does extend ArrayObject
. The code for Zend_Registry is somewhat simpler as a result.
If you want array chaining in PHP, you should really take a look into Chain. It's a really small project were you can use chaining methods like filter
and count
like you are coding Java!
$arr = array_filter(
array_map(
function ($v) { return rand(0, $v); },
array_fill(0, 10, 20)
),
function ($v) { return $v & 1; }
);
becomes
$chain = Chain::fill(0, 10, 20)
->map(function ($v) { return rand(0, $v); })
->filter(function ($v) { return $v & 1; });
Awesome right? More info you can find on this blog.
精彩评论