正如标题所暗示的那样,我正在尝试创建一个解析器并尝试找到最佳解决方案,将点名称空间中的内容转换为多维数组,以便
s1.t1.column.1 = size:33%
与
相同$source['s1']['t1']['column']['1'] = 'size:33%';
答案 0 :(得分:40)
试试这个号码......
function assignArrayByPath(&$arr, $path, $value, $separator='.') {
$keys = explode($separator, $path);
foreach ($keys as $key) {
$arr = &$arr[$key];
}
$arr = $value;
}
它将遍历键(默认情况下用.
分隔)以获取最终属性,然后对值进行赋值。
如果某些键不存在,则会创建它们。
答案 1 :(得分:14)
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]]]
您可以查看in the docs
如果您需要使用点符号来获取数据,则此过程会稍长,但会在array_get()
上提供,转换为this function(实际上是链接源显示所有与辅助数组相关的类)
/**
* 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);
}
它使用的最后一件事,但你可以跳过它,value()
是
if (! function_exists('value')) {
/**
* Return the default value of the given value.
*
* @param mixed $value
* @return mixed
*/
function value($value)
{
return $value instanceof Closure ? $value() : $value;
}
}
答案 2 :(得分:2)
我建议使用dflydev/dot-access-data。
如果您不熟悉使用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');
答案 3 :(得分:2)
您可以使用此函数将点符号数组转换为多维数组。
function flattenToMultiDimensional(array $array, $delimiter = '.')
{
$result = [];
foreach ($array as $notations => $value) {
// extract keys
$keys = explode($delimiter, $notations);
// reverse keys for assignments
$keys = array_reverse($keys);
// set initial value
$lastVal = $value;
foreach ($keys as $key) {
// wrap value with key over each iteration
$lastVal = [
$key => $lastVal
];
}
// merge result
$result = array_merge_recursive($result, $lastVal);
}
return $result;
}
示例:
$array = [
'test.example.key' => 'value'
];
print_r(flattenToMultiDimensional($array));
输出:
Array
(
[test] => Array
(
[example] => Array
(
[key] => value
)
)
)
答案 4 :(得分:-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
答案 5 :(得分:-2)
我很确定您正在尝试这样做来存储一些配置数据或类似数据。
我强烈建议您将此类文件保存为.ini
并使用parse_ini_file()函数将配置数据更改为多维数组。就像这个简单
$confArray = parse_ini_file("filename.ini");
var_dump($confArray);
答案 6 :(得分:-3)
又快又脏......
<?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);
答案 7 :(得分:-3)
我找到了一个适用于我的解决方案:Convert Flat PHP Array to Nested Array based on Array Keys因为我有一个基于带有不同键的.ini文件的数组,所以我做了一个小modification of that script并为我工作。
我的阵列看起来像这样:
[resources.db.adapter] => PDO_MYSQL
[resources.db.params.host] => localhost
[resources.db.params.dbname] => qwer
[resources.db.params.username] => asdf
...
根据要求,这是我描述的代码正在为我工作的代码:
<?php
echo "remove the exit :-)"; exit;
$db_settings = parse_ini_file($_SERVER['DOCUMENT_ROOT'].'/website/var/config/app.ini');
echo "<pre>";
print_r($db_settings);
echo "</pre>";
$resources = array();
foreach ($db_settings as $path => $value) {
$ancestors = explode('.', $path);
set_nested_value($resources, $ancestors, $value);
}
echo "<pre>";
print_r($resources);
echo "</pre>";
/**
* Give it and array, and an array of parents, it will decent into the
* nested arrays and set the value.
*/
function set_nested_value(array &$arr, array $ancestors, $value) {
$current = &$arr;
foreach ($ancestors as $key) {
// To handle the original input, if an item is not an array,
// replace it with an array with the value as the first item.
if (!is_array($current)) {
$current = array( $current);
}
if (!array_key_exists($key, $current)) {
$current[$key] = array();
}
$current = &$current[$key];
}
$current = $value;
}
这是parse_ini_file()读取的.ini文件的来源:
Array
(
[resources.db.adapter] => PDO_MYSQL
[resources.db.params.host] => localhost
[resources.db.params.dbname] => dbname
[resources.db.params.username] => dbname_user
[resources.db.params.password] => qwerqwerqwerqwer
[resources.db.params.charset] => utf8
[externaldb.adapter] => PDO_MYSQL
[externaldb.params.host] => localhost
[externaldb.params.dbname] => dbname2
[externaldb.params.username] => dbname_user2
[externaldb.params.password] => qwerqwerwqerqerw
[externaldb.params.charset] => latin1
)
这是上述代码的结果:
Array
(
[resources] => Array
(
[db] => Array
(
[adapter] => PDO_MYSQL
[params] => Array
(
[host] => localhost
[dbname] => dbname
[username] => dbname_user
[password] => qwerqwerqwerqwer
[charset] => utf8
)
)
)
[externaldb] => Array
(
[adapter] => PDO_MYSQL
[params] => Array
(
[host] => localhost
[dbname] => dbname2
[username] => dbname_user2
[password] => qwerqwerwqerqerw
[charset] => latin1
)
)
)