如何用单个字符串替换嵌套或多级数组的选择器

How to replace nested or multilevel array's selector by a single string

我正在尝试用 PHP 中的单个字符串替换多级数组选择器。下面我试过的代码是 运行 in PHP 7.2.

1.

$nested_array_selectors = '"my_array"]["my_key"]["my_elemnt"';
var_dump($my_instance->my_object[$nested_array_selectors]);

2.

$nested_array_selectors = 'my_array"]["my_key"]["my_elemnt';
var_dump($my_instance->my_object["$nested_array_selectors"]);

3.

$nested_array_selectors = '["my_array"]["my_key"]["my_elemnt"]';
var_dump($my_instance->my_object$nested_array_selectors);

我希望 $nested_array_selectors 可以像 $my_instance->my_object["my_array"]["my_key"]["my_element"]; 一样工作,但是 12 return "null" 和 3 得到一个 Parse error(当然)。

这实际上是不可能的,或者有人可以告诉我如何解决吗?

您尝试执行的操作无效,因为您正在尝试将变量转换为 PHP 代码。 PHP 不知道这是您的意图,也没有执行该代码。

PHP 确实有一个 eval() 结构可以让你做到这一点。

Caution The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

PHP manual for eval 解释更多。

Evaluate a string as PHP code

对于您的情况,以下代码将起作用。

$nested_array_selectors = '["my_array"]["my_key"]["my_elemnt"]';
eval('var_dump($my_instance->my_object' . $nested_array_selectors . ')');

像这样

$selectors = ["my_array","my_key","my_elemnt"];

$data = (array)$my_instance->my_object;

foreach($selectors as $k=>$v){
    if(isset($data[$k])){
        $data = $data[$k]; //reduce data by 1 level
    }else{
       $data = false;
       break;
    }
}

print_r($data);

基本上每次循环遍历数组中存在的 "selector" 时,都会将数组减少 1 级,例如,如果我们从这个

开始
$data = ['foo'=>['bar'=>['baz'=>1]]];
$selectors = ["foo","bar","baz"];

foreach($selectors as $v){
    print_r($data);
    if(isset($data[$v])){
        $data = $data[$v]; //reduce data by 1 level
    }else{
       $data = false;
       break;
    }
}
echo "\n---------- Final ------------\n";
print_r($data);

输出

Array
(
    [foo] => Array
        (
            [bar] => Array
                (
                    [baz] => 1
                )

        )

)
Array
(
    [bar] => Array
        (
            [baz] => 1
        )

)
Array
(
    [baz] => 1
)

---------- Final ------------
1

Sandbox

您可以在上面看到 "illustrated" 我们如何向下钻取到我们想要的元素。上面的每个 array 都是 $data 在按该选择器级别减少之前的状态。所以之后的那个显示了减少它的结果。所以第一个数组在应用 "foo" 之前,第二个数组在应用 "foo" 之后但在 "bar" 之前等等...

如果您想为 $selectors 使用逗号或其他字符串,只需使用 explode()preg_split() 将某个分隔符上的字符串分成一个简单的问题大批。例如:

 $selectors = "foo.bar.baz";
 $selectors = explode(".", $selectors ); //["foo","bar","baz"]
 //...

PS 如果提供了真实数据,我会使用它,但这是我测试它并解释它的唯一方法。

此外,这显然是一个很好的候选者,可以用以下函数创建一个函数:

function transverseWithKeys(array $array, $keys, $default=null, $glue='.'){
   if(!is_array($keys)) $keys = explode($glue,$keys);

   foreach($keys as $v){
       if(isset($array[$v])){
           $array= $array[$v]; //reduce data by 1 level
       }else{
           return $default;
       }
   }
   return $array;
}

希望对您有所帮助。