2011-12-13 83 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 

綁定是非常有用的,但沒有一個神奇的方法與語義別名它。