Вывести элемент массива

Горбушка

Ищу её...
Регистрация
2 Май 2008
Сообщения
3.444
Реакции
2.523
Есть массив, к примеру:

$row['car1']['color']['code'] = 1
$row['car2']['color']['code'] = 2

Есть переменная, которая хранит в себе путь:

$name = "['car2']['color']['code']";

Как вывести элемент массива с путём, как указано в переменной $name?

Тупое $row[$name] - конечно не работает.

На ум пришло только использование eval()...
 
Последнее редактирование:

sol_los

Мой дом здесь!
Регистрация
17 Окт 2011
Сообщения
423
Реакции
276
ты бы привел пример контекста в котором это работает, на первый взгляд - тут реализация не верна. зачем такие потуги закручивать?
 

Nei

Nosce te ipsum
Команда форума
Модератор
Регистрация
5 Сен 2009
Сообщения
688
Реакции
603
Вообще странно, что такой вариант не работает:
PHP:
$row['car2']['color']['code'] = 2;
$varname = "row['car2']['color']['code']";
echo $varname . '= ' . ${$varname};
При этом если просто убрать индексы массивов, то работает:
PHP:
$row = 2;
$varname = "row";
echo $varname . '= ' . ${$varname};
И вот так тоже будет работать:
PHP:
$row['car2']['color']['code'] = 2;
$varname = "row";
echo $varname . '= ' . ${$varname}['car2']['color']['code'];
Но как именно вот эту часть "['car2']['color']['code']" сделать переменной что-то у меня так слёту идей нет. Интересно было бы узнать, если кто подскажет как это сделать.

Как вариант отсюда
PHP:
$name = "['car2']['color']['code']"
выдрать сами индексы (регуляркой или explode) и дальше уже использовать индексы:
PHP:
$row[$index1][$index2][$index3]

Eval я бы в самую последнюю очередь использовал.
 

Горбушка

Ищу её...
Регистрация
2 Май 2008
Сообщения
3.444
Реакции
2.523
ты бы привел пример контекста в котором это работает, на первый взгляд - тут реализация не верна. зачем такие потуги закручивать?
Ну пример есть в первом посте.

Если просто интересно зачем оно мне - генерация отчёта по затраченному времени специалистами с произвольной глубиной группировки. Т.е. я не знаю сколько элементов будет у массива - 2, 4, 8... Да хоть 16... Сколько ПМ захочет - столько и будет.
Мне нужно вывести суммы по каждому уровню группировки. Естественно БД мне считает только самый нижний уровнень.
Вот и приходится собирать имя пути в массиве.

Nei, вот я тоже всегда думал, что это простая задача, оказалось - нет :(
Пока сделал на eval - система внетренняя, корпоративная, в интернет не торчит, данные приходят из ещё более закрытой БД. В общем, да, не секьюрно, но чтобы это взломать - надо взломать ещё 4 системы )

Я тут ещё больше удивился - у PHP нельзя просто получить первый элемент массива.
Есть array_shift - он тебе вернёт 1-ый элемент... Всё круто, но он, сцука, вырежет его из массива...
Ещё один костыль на ровном месте :D

Кстати, пришёл в голову такой костыль:
$name = "row['car2']['color']['code']";
echo ${$name};
Но, увы, нет... Undefined variable $row['car2']['color']['code']
Т.е. он не воспринимает это как массив :(

explode не вариант, потому что он там пробегается примерно 40 000 раз... Отчёт будет генерироваться 2 года )))
 
  • Нравится
Реакции: Nei

sol_los

Мой дом здесь!
Регистрация
17 Окт 2011
Сообщения
423
Реакции
276
Ну пример есть в первом посте.
я имел ввиду другое. нужен был пример, как это работает на фронте, если в бэке приходится крутить подобную херню.
т.е. реализация изначально не верна и как итог проблема в том, что данные из б.д. получаются не верно, следовательно и обрабатывать их сложно, да и затратно.

Кстати, пришёл в голову такой костыль:
$name = "row['car2']['color']['code']";
echo ${$name};
Но, увы, нет... Undefined variable $row['car2']['color']['code']

для php это просто строка и при обработке все эти символы экранируются
 
  • Нравится
Реакции: Nei

Nei

Nosce te ipsum
Команда форума
Модератор
Регистрация
5 Сен 2009
Сообщения
688
Реакции
603
Кстати, пришёл в голову такой костыль:
$name = "row['car2']['color']['code']";
echo ${$name};
Но, увы, нет... Undefined variable $row['car2']['color']['code']
Т.е. он не воспринимает это как массив :(

Да, я выше этот костыль и приводил в качестве примера и тот же результат.
Надо будет на stackoverflow запостить, посмотреть что напишут спецы) Но похоже, что через динамическое имя переменной всё-таки не выйдет решить вопрос.

Я тут ещё больше удивился - у PHP нельзя просто получить первый элемент массива.
Есть array_shift - он тебе вернёт 1-ый элемент... Всё круто, но он, сцука, вырежет его из массива...
Ещё один костыль на ровном месте
Ну, тут проще, начиная с версии php 7.3 можно получить первый индекс массива при помощи array_key_first и по нему получить значение. Если версия ниже 7.3, то да - костыль придётся использовать :oops:

для php это просто строка и при обработке все эти символы экранируются
странно, что не генерируется предупреждение, а просто "undefined variable"
 

Black#FFFFFF

Постоялец
Регистрация
19 Июл 2007
Сообщения
226
Реакции
169
Да, я выше этот костыль и приводил в качестве примера и тот же результат.
Надо будет на stackoverflow запостить, посмотреть что напишут спецы) Но похоже, что через динамическое имя переменной всё-таки не выйдет решить вопрос.


Ну, тут проще, начиная с версии php 7.3 можно получить первый индекс массива при помощи array_key_first и по нему получить значение. Если версия ниже 7.3, то да - костыль придётся использовать :oops:


странно, что не генерируется предупреждение, а просто "undefined variable"

До 7.3 key current next end в помощь. current -> next -> end двигают массив, key получает нужный для сравнения ключ.

Mysql/Mariadb поддерживает хранение Json, Json из текстовой строки легко перегнать в переменную в short версии массива.

Плюс никто не мешает тебе хранить массивы в тексте в мускуле в json_encode, serialize виде.

Еще выход: писать все это в файл и include файлы. Но выход так себе.
 

Black#FFFFFF

Постоялец
Регистрация
19 Июл 2007
Сообщения
226
Реакции
169
Я тут ещё больше удивился - у PHP нельзя просто получить первый элемент массива.
Есть array_shift - он тебе вернёт 1-ый элемент... Всё круто, но он, сцука, вырежет его из массива...

Хех, это old school, это current - первый элемент массива, а key -> его ключ, и дальше next, пока не false. А потом rewind. И сравни с $name. Вот и вся задача.

PHP:
<?php
     
$row['car4']['color']['set']['get'] = 1;
$row['car4']['color']['code']['get'] = 3;
$row['car1']['color']['code'] = 4;
$row['car2']['color']['code'] = 2;
$row['car2']['color1'] = 6;
$row['car3'] = 5;
$name = "['car2']['color']['code']";
$names = get_level_name($row);
function get_level_name($row){
 
    $names = array();
 
    foreach($row as $key => $value) {
     
        $name = "['".$key."']";
     
        if(is_array($value)){
            get_sub_tree($value,$name,$names);
        } else {
            $names[$name] = $value;
        }
     
    }
 
    return $names;
 
}
function get_sub_tree($values,$name,&$names){
 
   foreach($values as $key => $value){
 
        $subName = $name."['".$key."']";
         
        if(is_array($value)){
            $subName = get_sub_tree($value,$subName,$names);
        } else {
            $names[$subName] = $value;
        }
 
    }
 
    return $subName;
}
print_r($names);
if(isset($names[$name])){
echo $names[$name];
}

дальше разберешься. по сути рекурсией получаю все ключи в массив, а дальше достаточно взять твою переменную и проверить на isset, если такой ключ есть, то получишь его значение, там где echo.

Я входной массив усложнил в виде дерева с несколькими ветками (для теста).
И распечатал тебе для наглядности.

Плюс в конце получаешь свою двойку по необходимому ключу.

PHP:
Array
(
    [['car4']['color']['set']['get']] => 1
    [['car4']['color']['code']['get']] => 3
    [['car1']['color']['code']] => 4
    [['car2']['color']['code']] => 2
    [['car2']['color1']] => 6
    [['car3']] => 5
)
2

Рекурсия поддерживает любой уровень вложенности массива. И никаких eval.
Но лучше разберись с таблицами. Там задачу решить проще.

Код проверял в sandbox 7.4.7. Но работать будет в любом php. Даже php 4.
 
Последнее редактирование:

Горбушка

Ищу её...
Регистрация
2 Май 2008
Сообщения
3.444
Реакции
2.523
Black#FFFFFF, в том и проблема, что current - это не первый, а текущий. Хотя, как я понял, до вызова функции next или аналогичных - он всё же берёт всегда первый, не смотря на всякие foreach и т.д.

По рекурсии - да, думал в эту сторону, но при получении большого количества строк из БД - выполнять это для каждой... Хотя, может оно и правильно... Подумаю, может переделаю на рекурсию...
 

Q_BASIC

Хранитель порядка
Регистрация
30 Ноя 2013
Сообщения
516
Реакции
1.239
Ну пример есть в первом посте.

Если просто интересно зачем оно мне - генерация отчёта по затраченному времени специалистами с произвольной глубиной группировки. Т.е. я не знаю сколько элементов будет у массива - 2, 4, 8... Да хоть 16... Сколько ПМ захочет - столько и будет.
Мне нужно вывести суммы по каждому уровню группировки. Естественно БД мне считает только самый нижний уровнень.
Вот и приходится собирать имя пути в массиве.

Nei, вот я тоже всегда думал, что это простая задача, оказалось - нет :(
Пока сделал на eval - система внетренняя, корпоративная, в интернет не торчит, данные приходят из ещё более закрытой БД. В общем, да, не секьюрно, но чтобы это взломать - надо взломать ещё 4 системы )

Я тут ещё больше удивился - у PHP нельзя просто получить первый элемент массива.
Есть array_shift - он тебе вернёт 1-ый элемент... Всё круто, но он, сцука, вырежет его из массива...
Ещё один костыль на ровном месте :D

Кстати, пришёл в голову такой костыль:
$name = "row['car2']['color']['code']";
echo ${$name};
Но, увы, нет... Undefined variable $row['car2']['color']['code']
Т.е. он не воспринимает это как массив :(

explode не вариант, потому что он там пробегается примерно 40 000 раз... Отчёт будет генерироваться 2 года )))
reset функция есть с php4 ещё. Возвращает первый элемент ничего не вырезая
 
Сверху