“阵列链接”的最佳解决方案

时间:2010-09-15 21:15:54

标签: php multidimensional-array php-5.3

对于我的项目,我编写了一个小的配置类,用于从.ini文件加载其数据。它会覆盖magic __get()方法,以便提供对(只读)配置值的简化访问。

示例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访问数组的第一级,使用Config::getInstance()->General['user']访问值。我真正想要的是通过执行Config::getInstance()->General->user(语法糖)来访问所有配置变量。数组不是对象,而是“ - &gt;”没有定义,所以这只是失败。

我想到了一个解决方案,并希望得到一些公众舆论:

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 个答案:

答案 0 :(得分:1)

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

Zend Framework有一个类似的组件,他们称之为Zend_Config。您可以download来源并检查它们是如何实现的。他们不必一直延伸到ArrayObject

Zend_Registry类具有相似的用法,并且扩展了ArrayObject。 Zend_Registry的代码因此更简单。

答案 1 :(得分:0)

如果要使用PHP进行数组链接,则应真正研究Chain。如果您可以像编码Java一样使用filtercount之类的链接方法,那将是一个非常小的项目!

$arr = array_filter(
    array_map(
        function ($v) { return rand(0, $v); },
        array_fill(0, 10, 20)
    ),
    function ($v) { return $v & 1; }
);

成为

$chain = Chain::fill(0, 10, 20)
    ->map(function ($v) { return rand(0, $v); })
    ->filter(function ($v) { return $v & 1; });

太棒了吧? 您可以在this blog上找到更多信息。