#php #arrays #string #drupal #syntax
#php #массивы #строка #drupal #синтаксис
Вопрос:
Я пытаюсь заменить селекторы многоуровневого массива одной строкой в 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 возвращают «null», а 3 получает Parse error
(конечно).
Это действительно невозможно или кто-нибудь может сказать мне, как это исправить?
Ответ №1:
Что-то вроде этого
$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
like с запятыми или что-то еще, достаточно просто использовать explode()
or 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;
}
Надеюсь, это поможет.
Комментарии:
1. @ArtisticPhoenix. Спасибо за ваше терпеливое объяснение. У меня небольшая проблема с пониманием вашего кода, это моя вина. Проще сделать, чем сказано для программирования, я попробую.
2.
I have a little problem for understanding your code
— если вы можете выразить это словами, не стесняйтесь спрашивать, и я попытаюсь это объяснить. Спасибо!
Ответ №2:
То, что вы пытаетесь сделать, не сработает, потому что вы пытаетесь преобразовать переменную в 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 . ')');
Комментарии:
1. Спасибо за ответ. Кстати, в моем случае мне нужно:
$my_instance->my_object["my_array"]["my_key"]["my_element"];
чтобы$my_instance->my_object["$some_var"]
. Или любой другой, который мог бы сократить или интегрировать составные параметры.2. E. Спасибо. Фактически это самый близкий ответ, но ‘eval’ слишком опасен.