Использование строкового пути для установки данных вложенных массивов

У меня есть необычный случай использования, к которому я пытаюсь закодировать. Цель заключается в следующем: я хочу, чтобы клиент мог предоставить строку, такую ​​как:

"cars.honda.civic = On" 

Используя эту строку, мой код установит значение следующим образом:

 $data['cars']['honda']['civic'] = 'On'; 

Достаточно легко отметить вход клиента как таковой:

 $token = explode("=",$input); $value = trim($token[1]); $path = trim($token[0]); $exploded_path = explode(".",$path); 

Но теперь, как я могу использовать $ exploded path для установки массива, не делая ничего противного, как eval?

Используйте ссылочный оператор для получения последовательных существующих массивов:

 $temp = &$data; foreach($exploded as $key) { $temp = &$temp[$key]; } $temp = $value; unset($temp); 

Основываясь на ответе alexisdm :

 /** * Sets a value in a nested array based on path * See https://stackoverflow.com/a/9628276/419887 * * @param array $array The array to modify * @param string $path The path in the array * @param mixed $value The value to set * @param string $delimiter The separator for the path * @return The previous value */ function set_nested_array_value(&$array, $path, &$value, $delimiter = '/') { $pathParts = explode($delimiter, $path); $current = &$array; foreach($pathParts as $key) { $current = &$current[$key]; } $backup = $current; $current = $value; return $backup; } 
 $data = $value; foreach (array_reverse($exploded_path) as $key) { $data = array($key => $data); } 

Основываясь на ответе Уго Меды :

Эта версия

  • позволяет использовать его исключительно как getter (оставить исходный массив нетронутым)
  • исправляет фатальную ошибку, если встречается значение, отличное от массива ( Cannot create references to/from string offsets nor overloaded objects )

нет фатальной ошибки

 $a = ['foo'=>'not an array']; arrayPath($a, ['foo','bar'], 'new value'); 

$a теперь

 array( 'foo' => array( 'bar' => 'new value', ), ) 

Использовать в качестве геттера

 $val = arrayPath($a, ['foo','bar']); // returns 'new value' / $a remains the same 

Установить значение в null

 $v = null; // assign null to variable in order to pass by reference $prevVal = arrayPath($a, ['foo','bar'], $v); 

$prevVal – это "новое значение"
$a теперь

 array( 'foo' => array( 'bar' => null, ), ) 

 /** * set/return a nested array value * * @param array $array the array to modify * @param array $path the path to the value * @param mixed $value (optional) value to set * * @return mixed previous value */ function arrayPath(&$array, $path = array(), &$value = null) { $args = func_get_args(); $ref = &$array; foreach ($path as $key) { if (!is_array($ref)) { $ref = array(); } $ref = &$ref[$key]; } $prev = $ref; if (array_key_exists(2, $args)) { // value param was passed -> we're setting $ref = $value; // set the value } return $prev; } 

Хорошо протестированный и 100% рабочий код. Установите, получите, не задайте значения из массива, используя «родители». Родителями может быть либо array('path', 'to', 'value') либо строка path.to.value . На основе кода Drupal

  /** * @param array $array * @param array|string $parents * @param string $glue * @return mixed */ function array_get_value(array &$array, $parents, $glue = '.') { if (!is_array($parents)) { $parents = explode($glue, $parents); } $ref = &$array; foreach ((array) $parents as $parent) { if (is_array($ref) && array_key_exists($parent, $ref)) { $ref = &$ref[$parent]; } else { return null; } } return $ref; } /** * @param array $array * @param array|string $parents * @param mixed $value * @param string $glue */ function array_set_value(array &$array, $parents, $value, $glue = '.') { if (!is_array($parents)) { $parents = explode($glue, (string) $parents); } $ref = &$array; foreach ($parents as $parent) { if (isset($ref) && !is_array($ref)) { $ref = array(); } $ref = &$ref[$parent]; } $ref = $value; } /** * @param array $array * @param array|string $parents * @param string $glue */ function array_unset_value(&$array, $parents, $glue = '.') { if (!is_array($parents)) { $parents = explode($glue, $parents); } $key = array_shift($parents); if (empty($parents)) { unset($array[$key]); } else { array_unset_value($array[$key], $parents); } } с  /** * @param array $array * @param array|string $parents * @param string $glue * @return mixed */ function array_get_value(array &$array, $parents, $glue = '.') { if (!is_array($parents)) { $parents = explode($glue, $parents); } $ref = &$array; foreach ((array) $parents as $parent) { if (is_array($ref) && array_key_exists($parent, $ref)) { $ref = &$ref[$parent]; } else { return null; } } return $ref; } /** * @param array $array * @param array|string $parents * @param mixed $value * @param string $glue */ function array_set_value(array &$array, $parents, $value, $glue = '.') { if (!is_array($parents)) { $parents = explode($glue, (string) $parents); } $ref = &$array; foreach ($parents as $parent) { if (isset($ref) && !is_array($ref)) { $ref = array(); } $ref = &$ref[$parent]; } $ref = $value; } /** * @param array $array * @param array|string $parents * @param string $glue */ function array_unset_value(&$array, $parents, $glue = '.') { if (!is_array($parents)) { $parents = explode($glue, $parents); } $key = array_shift($parents); if (empty($parents)) { unset($array[$key]); } else { array_unset_value($array[$key], $parents); } } 

Разве ты не можешь это сделать

 $exp = explode(".",$path); $array[$exp[0]][$exp[1]][$exp[2]] = $value