Как заменить селектор вложенного или многоуровневого массива одной строкой - PullRequest
0 голосов
/ 28 марта 2019

Я пытаюсь заменить многоуровневые селекторы массивов одной строкой в ​​PHP. Код, который я пробовал, работает в 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"];, но 1 и 2 возвращают «ноль» и 3 получает Parse error (конечно).

Это на самом деле невозможно или кто-то может сказать мне, как это исправить?

Ответы [ 2 ]

0 голосов
/ 28 марта 2019

как то так

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

Обычно каждый раз, когда вы перебираете «селектор», который существует в массиве, вы уменьшаете массив на 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

Песочница

Вы можете увидеть «иллюстрированный» выше, как мы можем перейти к элементу, который мы хотим. Каждый array выше является состоянием $data до его снижения на этот уровень селекторов. Таким образом, один после этого показывает результаты его снижения. Таким образом, первый массив перед применением "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;
}

Надеюсь, это поможет.

0 голосов
/ 28 марта 2019

То, что вы пытаетесь сделать, не сработает, потому что вы пытаетесь преобразовать переменную в код PHP. PHP не знает, что это ваше намерение, и не выполняет этот код.

PHP имеет конструкцию eval(), которая позволяет вам сделать это.

Внимание! Языковая конструкция eval () очень опасна, потому что позволяет выполнять произвольный код PHP. Таким образом, его использование не рекомендуется. Если вы тщательно убедились, что нет другого выбора, кроме как используйте эту конструкцию, обратите особое внимание, чтобы не пропустить ни одного пользователя предоставил данные без предварительной проверки.

Руководство по PHP для eval объясняет больше.

Оценить строку как код PHP

В вашем случае будет работать следующий код.

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