Преобразовать точечный синтаксис как «this.that.other» в многомерный массив в PHP

Как следует из названия, я пытаюсь создать парсер и попытаться найти оптимальное решение для преобразования чего-либо из пространства имен точек в многомерный массив, так что

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 ...