Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用字符串路径设置嵌套数组数据_Php_Arrays_Token - Fatal编程技术网

Php 使用字符串路径设置嵌套数组数据

Php 使用字符串路径设置嵌套数组数据,php,arrays,token,Php,Arrays,Token,我有一个不寻常的用例,我正试图编写代码。目标是:我希望客户能够提供一个字符串,例如: "cars.honda.civic = On" 使用此字符串,我的代码将设置一个值,如下所示: $data['cars']['honda']['civic'] = 'On'; 很容易将客户输入标记为: $token = explode("=",$input); $value = trim($token[1]); $path = trim($token[0]); $exploded_path = explod

我有一个不寻常的用例,我正试图编写代码。目标是:我希望客户能够提供一个字符串,例如:

"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的操作呢?

使用reference操作符获取连续的现有数组:

$data = $value;
foreach (array_reverse($exploded_path) as $key) {
    $data = array($key => $data);
}
$temp = &$data;
foreach($exploded as $key) {
    $temp = &$temp[$key];
}
$temp = $value;
unset($temp);
你就不能这么做吗

$exp = explode(".",$path);
$array[$exp[0]][$exp[1]][$exp[2]] = $value
基于:

/**
*基于路径在嵌套数组中设置值
*看https://stackoverflow.com/a/9628276/419887
*
*@param array$array要修改的数组
*@param string$path数组中的路径
*@param mixed$value要设置的值
*@param string$分隔符路径的分隔符
*@返回上一个值
*/
函数集\u嵌套\u数组\u值(&$array,$path,&$value,$delimiter='/')){
$pathParts=分解($delimiter,$path);
$current=&$array;
foreach($pathParts作为$key){
$current=&$current[$key];
}
$backup=$current;
$current=$value;
返回$backup;
}
基于:

这个版本

  • 允许您仅将其用作getter(保持源数组不变)
  • 修复了遇到非数组值时出现的致命错误问题(
    无法创建对字符串偏移量或重载对象的引用
无致命错误示例

$a = ['foo'=>'not an array'];
arrayPath($a, ['foo','bar'], 'new value');
$a
现在是

array(
    'foo' => array(
        'bar' => 'new value',
    ),
)
array(
    'foo' => array(
        'bar' => null,
    ),
)
用作getter

$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' => 'new value',
    ),
)
array(
    'foo' => array(
        'bar' => null,
    ),
)


经过良好测试的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);
    }
}
你需要使用Symfony

这正是它的用途:

它将您的
$array
置于元素应设置的位置,并接受点分隔格式的
$keys
或后续键的数组

因此,在您的情况下,您只需通过以下方式即可实现预期结果:

$data=Arr::set([],“cars.honda.civic”,“On”);
//这相当于
$data=[
“汽车”=>[
‘本田’=>[
“思域”=>“开”,
],
],
];
此外,
$keys
参数也可以接受创建自动索引,因此您可以这样使用它:

$data=Arr::set([],“cars.honda.civic.[],“On”);
//为了得到
$data=[
“汽车”=>[
‘本田’=>[
“civic”=>[“On”],
],
],
];

我只是假设
$exp
的数量不是固定的!deceze是正确的-我不能假设我知道客户将提供多少节点。不过,感谢您的反馈。除非您使用类似于
数组\u合并\u递归的方法
,否则您将替换$data已经包含的以前的值。这实际上是一个很好的观点,假设
$data
已经包含值。是否有方法获取值而不是设置?@marairsossouw您的注释/问题很旧,但请看它是否有效。最后两行不是多余的吗?比如,如果我们需要取消设置
$temp
,那么为什么还要只在上面设置一行呢?@mohdadulmujib
$temp
是一行,最后一行写入引用的变量(在本例中是嵌套的数组项),最后一行删除引用,这样
$temp
就不会链接到该变量。啊。。。知道了。感谢您的解释。小调整:如果路径上的一个“节点”已设置,但不是数组,则此函数将是致命的<代码>$a=['foo'=>'不是数组'];设置嵌套数组($a,'foo/bar','new value')修复:如果(!is_array($current)){$current=array();}
您可以选择检查path是否为字符串,并使用explode转换为数组,例如,
$path=explode('.',$path)
因此可以使用流行的点表示法,例如,
$val=arrayPath($a,'foo.bar')“PHP致命错误:只能通过引用传递变量”在
arrayPath($a、['foo'、'bar']、'new value')感谢您发布此信息!我刚开始写我自己的版本,对于一个定制的Drupal模块lol,我不知道这是在核心。这正是我需要的!
Arr::set($array, $keys, $value);