PHP通过引用变量从数组中赋值。更改变量将更改数组中的值

时间:2011-12-13 11:14:13

标签: php arrays loops

我有一堆字符串,如" memory.caching"和" server.base.url"。在我的配置对象中键的每一部分"。"等于一个数组中的一个键,该值可能是另一个数组,最后一个是值,所以" memory.caching"等于。

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

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

有点可怕,但绝对有效的方法是使用eval()(邪恶):

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

答案 2 :(得分: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

Bind非常有用,但没有一种神奇的方法可以用语义对它进行别名。