Как следует из названия, я пытаюсь создать парсер и попытаться найти оптимальное решение для преобразования чего-либо из пространства имен точек в многомерный массив, так что
s1.t1.column.1 = size:33%
будет таким же, как
$source['s1']['t1']['column']['1'] = 'size:33%';
Попробуйте этот номер …
function assignArrayByPath(&$arr, $path, $value, $separator='.') { $keys = explode($separator, $path); foreach ($keys as $key) { $arr = &$arr[$key]; } $arr = $value; }
CodePad
Он будет проходить через ключи (с разделителем по умолчанию), чтобы перейти к окончательному свойству, а затем выполнить присвоение значения.
Если некоторые из ключей отсутствуют, они создаются.
FYI В Laravel у нас есть вспомогательная функция array_set()
которая переводит в эту функцию
/** * Set an array item to a given value using "dot" notation. * * If no key is given to the method, the entire array will be replaced. * * @param array $array * @param string $key * @param mixed $value * @return array */ public static function set(&$array, $key, $value) { if (is_null($key)) { return $array = $value; } $keys = explode('.', $key); while (count($keys) > 1) { $key = array_shift($keys); // If the key doesn't exist at this depth, we will just create an empty array // to hold the next value, allowing us to create the arrays to hold final // values at the correct depth. Then we'll keep digging into the array. if (! isset($array[$key]) || ! is_array($array[$key])) { $array[$key] = []; } $array = &$array[$key]; } $array[array_shift($keys)] = $value; return $array; }
Это просто, как
$array = ['products' => ['desk' => ['price' => 100]]]; array_set($array, 'products.desk.price', 200); // ['products' => ['desk' => ['price' => 200]]]
Вы можете проверить его в документах
Если вам нужно вместо этого получить данные с помощью точечной нотации, процесс будет немного длиннее, но будет выполнен на пластинке с помощью array_get()
которая переводится на эту функцию (на самом деле связанный источник показывает вам весь класс, связанный с вспомогательным массивом)
/** * Get an item from an array using "dot" notation. * * @param \ArrayAccess|array $array * @param string $key * @param mixed $default * @return mixed */ public static function get($array, $key, $default = null) { if (! static::accessible($array)) { return value($default); } if (is_null($key)) { return $array; } if (static::exists($array, $key)) { return $array[$key]; } if (strpos($key, '.') === false) { return $array[$key] ?? value($default); } foreach (explode('.', $key) as $segment) { if (static::accessible($array) && static::exists($array, $segment)) { $array = $array[$segment]; } else { return value($default); } } return $array; }
по/** * Get an item from an array using "dot" notation. * * @param \ArrayAccess|array $array * @param string $key * @param mixed $default * @return mixed */ public static function get($array, $key, $default = null) { if (! static::accessible($array)) { return value($default); } if (is_null($key)) { return $array; } if (static::exists($array, $key)) { return $array[$key]; } if (strpos($key, '.') === false) { return $array[$key] ?? value($default); } foreach (explode('.', $key) as $segment) { if (static::accessible($array) && static::exists($array, $segment)) { $array = $array[$segment]; } else { return value($default); } } return $array; }
Как вы можете видеть, он использует два субметода, accessible()
и exists()
/** * Determine whether the given value is array accessible. * * @param mixed $value * @return bool */ public static function accessible($value) { return is_array($value) || $value instanceof ArrayAccess; }
А также
/** * Determine if the given key exists in the provided array. * * @param \ArrayAccess|array $array * @param string|int $key * @return bool */ public static function exists($array, $key) { if ($array instanceof ArrayAccess) { return $array->offsetExists($key); } return array_key_exists($key, $array); }
Я бы предложил использовать данные dflydev / dot-access .
Если вы не знакомы с использованием Composer, перейдите на https://getcomposer.org/ для введения, чтобы вы могли загружать и автозагружать пакет как зависимость от вашего проекта.
Когда у вас есть пакет, вы можете загрузить многомерный массив в объект Data:
use Dflydev\DotAccessData\Data; $data = new Data(array( 's1' => array( 't1' => array( 'column' => array( '1' => 'size:33%', ), ), ), );
И получить доступ к значениям с помощью точечной нотации:
$size = $username = $data->get('s1.t1.column.1');
Хотя pasrse_ini_file () также может выводить многомерный массив, я представлю другое решение. Zend_Config_Ini ()
$conf = new Zend_COnfig_Ini("path/to/file.ini"); echo $conf -> one -> two -> three; // This is how easy it is to do so //prints one.two.three
Я уверен, что вы пытаетесь сделать это, чтобы сохранить некоторые данные конфигурации или аналогичные.
Я настоятельно рекомендую вам сохранить такой файл как .ini
и использовать функцию parse_ini_file () для изменения данных конфигурации в многомерном массиве. Так просто, как это
$confArray = parse_ini_file("filename.ini"); var_dump($confArray);
Быстро и грязно…
<?php $input = 'one.two.three = four'; list($key, $value) = explode('=', $input); foreach (explode('.', $key) as $keyName) { if (false === isset($source)) { $source = array(); $sourceRef = &$source; } $keyName = trim($keyName); $sourceRef = &$sourceRef[$keyName]; } $sourceRef = $value; unset($sourceRef); var_dump($source);
с<?php $input = 'one.two.three = four'; list($key, $value) = explode('=', $input); foreach (explode('.', $key) as $keyName) { if (false === isset($source)) { $source = array(); $sourceRef = &$source; } $keyName = trim($keyName); $sourceRef = &$sourceRef[$keyName]; } $sourceRef = $value; unset($sourceRef); var_dump($source);
Я нашел решение, которое сработало для меня в: Преобразовать Flat PHP Array в Nested Array на основе Array Keys, и поскольку у меня был массив, основанный на файле .ini с разными ключами, я сделал небольшую модификацию этого скрипта и сделал работу для меня.
Мой массив выглядел так:
[resources.db.adapter] => PDO_MYSQL [resources.db.params.host] => localhost [resources.db.params.dbname] => qwer [resources.db.params.username] => asdf ...