2011-12-13 84 views
1

我有一堆字符串,如“memory.caching”和“server.base.url”。在我的配置对象的每个部分的密钥“。”等于数组中的一个键,该值可以是另一个数组,最后一个值是“memory.caching”等于的值。PHP通过引用给变量赋值数组。更改变量会改变数组中的值

$config = array(
    "memory" => array(
    "caching" => true 
) 
); 

我想创建一个setter方法。我已经结束了下面的代码,但这不适用于三个或四个深度级别。我怎么可以不添加多个else/if子句呢。

public function set($k, $v) { 
    $parts = explode(".", $k); 

    // Start sucky code. 
    if (count($parts) == 2) 
    { 
    $this->config[$parts[0]][$parts[1]] = $val; 
    } 
} 

我正在考虑某些形式的循环与下面的引用分配,但我不能让它工作。

public function set($k, $v) { 
    $parts = explode(".", $k); 

    $tmp = $this->config; 
    foreach ($parts as $p) { 
    $tmp &= $tmp[$p]; 
    } 

    $tmp = $v; 
} 

关于如何实现这一点的任何想法?

回答

2

要设置的值...

public function set($path, $value, $delimiter = '.') { 

    $tokens = explode($delimiter, $path); 

    $currentPiece = &$this->config; 

    foreach($tokens as $token) { 
     $currentPiece = &$currentPiece[$token]; 
    } 

    $currentPiece = $value; 

} 

CodePad

为了得到一个值...

public function get($path, $delimiter = '.') { 

    $tokens = explode($delimiter, $path); 

    $currentPiece = $this->config; 

    while ($token = array_shift($tokens)) { 
     $currentPiece = $currentPiece[$token]; 
    } 

    return $currentPiece; 

} 

CodePad

+0

太棒了。我只是键入一个递归函数来完成这项工作,但你的工作非常出色。 :D – Turbotoast

+0

是的,这将给出正确的$部分,但如果我添加$ piece = $ newValue;并转储$配置,然后$配置中的值没有改变,这就是我以后,对不起,如果这不明确:) – Gcoop

+0

同意问题是$ config是一个嵌套关联数组,我使用像“memory.caching”这样的键可以获得一个值,这很好,除非以一种很好的方式设置值是棘手的。理想的解决方案是重写数值如何放入$ config中,因此它不是嵌套的关联数组!但我正在努力削减一个角落,而不是那么做! :) – Gcoop

0

一个稍微可怕的,但肯定工程方法,这是使用eval()(邪):

public function set($k, $v) { 
    eval('$this->config["'.implode('"]["', explode(".", $k)).'"] = $v;'); 
} 
0

尽管这个问题已经被回答(并接受)我就抛出这个版本出来有对未来的访客:

可能会丢失一些检查,我有这几个版本踢左右

class Map 
{ 

    protected $_array = array(); 

    protected $_separator; 

    public static function get(Array $array, $key, $separator) 
    { 
     $parts = explode($separator, $key); 
     $key = array_shift($parts); 
     while (!empty($parts)) 
     { 
      if (!isset($array[$key]) || !is_array($array[$key])) 
      { 
       return null; 
      } 
      $array = &$array[$key]; 
      $key = array_shift($parts); 
     } 
     return isset($array[$key]) ? $array[$key] : null; 
    } 

    public static function has(Array $array, $key, $separator) 
    { 
     $parts = explode($separator, $key); 
     $key = array_shift($parts); 
     while (!empty($parts)) 
     { 
      if (!isset($array[$key]) || !is_array($array[$key])) 
      { 
       return false; 
      } 
      $array = &$array[$key]; 
      $key = array_shift($parts); 
     } 
     return isset($array[$key]); 
    } 

    public static function set(&$array, $key, $value, $separator) 
    { 
     $parts = explode($separator, $key); 
     $key = array_shift($parts); 
     while (!empty($parts)) 
     { 
      if (!isset($array[$key]) || !is_array($array[$key])) 
      { 
       $array[$key] = array(); 
      } 
      $array = &$array[$key]; 
      $key = array_shift($parts); 
     } 
     $array[$key] = $value; 
    } 

    public static function bind(&$array, $key, &$variable, $separator) 
    { 
     $parts = explode($separator, $key); 
     $key = array_shift($parts); 
     while (!empty($parts)) 
     { 
      if (!isset($array[$key]) || !is_array($array[$key])) 
      { 
       $array[$key] = array(); 
      } 
      $array = &$array[$key]; 
      $key = array_shift($parts); 
     } 
     if (isset($array[$key])) 
     { 
      $variable = $array[$key]; 
     } 
     $array[$key] = &$variable; 
    } 

    public static function remove(&$array, $key, $separator) 
    { 
     $parts = explode($separator, $key); 
     $key = array_shift($parts); 
     while (!empty($parts)) 
     { 
      if (!isset($array[$key]) || !is_array($array[$key])) 
      { 
       return; 
      } 
      $array = &$array[$key]; 
      $key = array_shift($parts); 
     } 
     unset($array[$key]); 
    } 

    public function __construct(&$array, $separator) 
    { 
     if (!is_array($array)) 
     { 
      $array = array(); 
     } 
     $this->_array = $array; 
     $this->_separator = (string) $separator; 
    } 

    public function __get($key) 
    { 
     return static::get($this->_array, $key, $this->_separator); 
    } 

    public function __isset($key) 
    { 
     return static::has($this->_array, $key, $this->_separator); 
    } 

    public function __set($key, $value) 
    { 
     static::set($this->_array, $key, $value, $this->_separator); 
    } 

    public function __unset($key) 
    { 
     static::remove($this->_array, $key, $this->_separator); 
    } 

    public function get_array() 
    { 
     return $this->_array; 
    } 

} 

而且使用它像:

$array = array(
    'foo' => array(
     'bar' => array(
      'hello' => 'world', 
     ), 
    ), 
); 
$map = new Map($array, '.'); 

var_dump($map->{'foo.bar.hello'}); 
//string(5) "world" 

$map->{'foo.bar.goodbye'} = 'universe'; 
unset($map->{'foo.bar.hello'}); 
var_dump($map->get_array()); 
// array(1) { 
// ["foo"]=> 
// array(1) { 
//  ["bar"]=> 
//  array(1) { 
//  ["goodbye"]=> 
//  string(8) "universe" 
//  } 
// } 
// } 

var_dump(isset($map->{'foo.bar.goodbye'})); 
// true 

绑定是非常有用的,但没有一个神奇的方法与语义别名它。