“Array chaining”的最佳解决方案

问题描述:

对于我的项目,我编写了一个小配置类,它从.ini文件加载其数据。它会覆盖魔术__get()方法,以提供对(只读)配置值的简化访问。“Array chaining”的最佳解决方案

例config.ini.php:

;<?php exit; ?> 
[General] 
auth = 1 
user = "halfdan" 

[Database] 
host = "127.0.0.1" 

我的配置类(单例模式 - 在这里的简化)看起来像这样:

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]; 
    } 
} 

载入的配置会产生这样的阵列结构:

array(
    "General" => array(
    "auth" => 1, 
    "user" => "halfdan" 
), 
    "Database" => array(
    "host" => "127.0.0.1" 
) 
) 

可以通过做访问数组的第一级,以及使用Config::getInstance()->General['user']的值。我真正想要的是通过做Config::getInstance()->General->user(语法糖)来访问所有配置变量。该数组不是一个对象,“ - >”没有定义,所以这只是失败。

我想到了一个解决方案,并希望得到一些关于它的舆论:

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]; 
    } 
    } 
} 

这让我我的链配置访问。当我使用PHP 5.3时,让ConfigArray扩展ArrayObject(在5.3中默认激活SPL)也是一个好主意。

任何建议,改进,意见?

+2

如果你真的想为' - >'交换'[]',我会选择一个裸露的ArrayObject,但是我不想那样改变它。每次请求时创建一个_new_对象将是一个麻烦,但我会递归地走数组,并将数组修改为arrayobjects只有一次。 – Wrikken 2010-09-15 21:28:41

+0

@Wrikken:确实,在真实的实现中会改变这种行为。 – halfdan 2010-09-15 21:49:38

如果$this->config数组的元素也是Config类的实例,那么它可以工作。

Zend Framework有一个类似的组件,他们称之为Zend_Config。您可以download来源,并检查他们如何实施它。他们不必一路去扩展ArrayObject

Zend_Registry类具有类似的用法,它的确扩展了ArrayObject。 Zend_Registry的代码因此更简单一些。

+0

看着Zend_Config :: __构造:他们为更深的数组维度创建'new self($ value,..)'。 – halfdan 2010-09-15 21:39:40