PHP присваивает значение из массива по ссылке на переменную. Изменение переменной изменит значение в массиве - PullRequest
1 голос
/ 13 декабря 2011

У меня есть несколько строк, таких как «memory.caching» и «server.base.url». Внутри моего объекта конфигурации каждая часть ключа "." равно ключу в массиве, значение может быть другим массивом, а последним будет значение, так что «memory.caching» будет равно.

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

Я хочу создать метод установки. Я закончил с приведенным ниже кодом, но это не будет работать для трех или четырех уровней глубины. Как я могу сделать это без добавления нескольких предложений 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 ]

2 голосов
/ 13 декабря 2011

Чтобы установить значение ...

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 голосов
/ 06 января 2012

Хотя на этот вопрос с тех пор был дан ответ ( и принято ), я просто добавлю эту версию для будущих посетителей:

( Возможно, некоторые из них отсутствуютпроверок, у меня есть несколько версий этого )

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 очень полезен, но неесть магический метод для псевдонима с семантически.

0 голосов
/ 13 декабря 2011

Один немного ужасный, но определенно работающий подход к этому заключается в использовании eval() (зло):

public function set($k, $v) {
  eval('$this->config["'.implode('"]["', explode(".", $k)).'"] = $v;');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...