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