У меня есть необычный случай использования, к которому я пытаюсь закодировать. Цель заключается в следующем: я хочу, чтобы клиент мог предоставить строку, такую как:
"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); }
Основываясь на ответе Уго Меды :
Эта версия
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