转换点语法,如;“这个.那个.其他”;在PHP中实现多维数组

转换点语法,如;“这个.那个.其他”;在PHP中实现多维数组,php,parsing,Php,Parsing,正如标题所暗示的,我正在尝试创建一个解析器,并试图找到将点名称空间中的内容转换为多维数组的最佳解决方案,以便 s1.t1.column.1 = size:33% 就跟 $source['s1']['t1']['column']['1'] = 'size:33%'; 试试这个号码 function assignArrayByPath(&$arr, $path, $value, $separator='.') { $keys = explode($separator, $path

正如标题所暗示的,我正在尝试创建一个解析器,并试图找到将点名称空间中的内容转换为多维数组的最佳解决方案,以便

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;
}

它将循环通过键(默认情况下以
分隔)到达最终属性,然后对值进行赋值


如果某些键不存在,则会创建它们。

我很确定您正在尝试这样做以存储一些配置数据或类似数据

我强烈建议您将此类文件保存为
.ini
,并使用函数将配置数据更改为多维数组。就这么简单

$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);
虽然pasrse_ini_file()也可以产生多维数组,但我将提供一个不同的解决方案

$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文件的数组,有不同的键,所以我做了一个很小的数组,为我工作

我的数组如下所示:

[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;
}
这是上述代码的结果:

$size = $username = $data->get('s1.t1.column.1');

仅供参考,在Laravel中,我们有一个
array\u set()
helper函数,在这个函数中进行翻译

方法使用点表示法存储在数组中
/**
*使用“点”符号将数组项设置为给定值。
*
*如果没有为该方法提供键,则将替换整个数组。
*
*@param数组$array
*@param string$key
*@param混合$value
*@return数组
*/
公共静态函数集(&$array,$key,$value)
{
如果(为空($key)){
返回$array=$value;
}
$keys=分解('.',$key);
同时(计数($keys)>1){
$key=数组移位($key);
//如果键在此深度不存在,我们将创建一个空数组
//来保存下一个值,允许我们创建数组来保存final
//值在正确的深度。然后我们将继续挖掘数组。
如果(!isset($array[$key])| |!is_array($array[$key])){
$array[$key]=[];
}
$array=&$array[$key];
}
$array[array_shift($keys)]=$value;
返回$array;
}
这很简单

$array=['products'=>['desk'=>['price'=>100]];
数组_集($数组,'products.desk.price',200);
//['products'=>['desk'=>['price'=>200]]
你可以查一下

如果您需要使用点表示法获取数据,则该过程会稍微长一点,但由
array\u get()
提供在一个盘子上,它转换为(实际上链接的源代码显示了所有与helper数组相关的类)

方法使用点表示法从数组中读取
/**
*使用“点”符号从数组中获取项。
*
*@param\ArrayAccess | array$array
*@param string$key
*@param混合$default
*@返回混合
*/
公共静态函数get($array,$key,$default=null)
{
如果(!static::accessible($array)){
返回值($default);
}
如果(为空($key)){
返回$array;
}
if(static::exists($array,$key)){
返回$array[$key];
}
if(strpos($key,'.')==false){
返回$array[$key]??值($default);
}
foreach(分解('.',$key)为$segment){
if(static::accessible($array)&&static::exists($array,$segment)){
$array=$array[$segment];
}否则{
返回值($default);
}
}
返回$array;
}
如您所见,它使用两个子方法,
accessible()
exists()

/**
*确定给定值是否可访问数组。
*
*@param混合$value
*@returnbool
*/
可访问的公共静态函数($value)
{
返回的是ArrayAccess的_数组($value)| |$value实例;
}

/**
*确定提供的数组中是否存在给定的密钥。
*
*@param\ArrayAccess | array$array
*@param string | int$key
*@returnbool
*/
存在公共静态函数($array,$key)
{
if($array instanceof ARRAYAACCESS){
返回$array->offsetExists($key);
}
返回数组\u key\u存在($key,$array);
}
它使用的最后一个东西,但您可能可以跳过它,是
value()
,它是

如果(!function_存在('value')){
/**
*返回给定值的默认值。
*
*@param混合$value
*@返回混合
*/
函数值($value)
{
返回闭包的$value实例?$value():$value;
}
}
我建议使用

如果您不熟悉Composer的使用,请转到进行介绍,这样您就可以下载并自动加载该包,作为项目的依赖项

获得包后,可以将多维数组加载到数据对象中:

Array
(
    [test] => Array
        (
            [example] => Array
                (
                    [key] => value
                )

        )

)
并使用点符号访问值:


可以使用此函数将点符号arrray转换为多维数组

函数flattToMultidimensional(数组$array,$delimiter='))
{
$result=[];
foreach($array作为$notations=>$value){
//提取密钥
$keys=explode($delimiter,$notations);
//为作业反转键
$keys=数组_反转($keys);
//设定初始值
$lastVal=$value;
foreach($key作为$key){
//在每次迭代中使用键包装值
$lastVal=[
$key=>$lastVal
];
}
//合并结果
$result=array\u merge\u recursive($result$lastVal);
}
返回$result;
}
例如:

$array=[
'test.example.key'=>'值'
];
打印(平面到多维($array));
输出:


我不明白你为什么要重写
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');
Array
(
    [test] => Array
        (
            [example] => Array
                (
                    [key] => value
                )

        )

)