Или можно перефразировать задачу — Как получить многомерный массив из одномерного (плоского), или Получить вложенный массив из одномерного.
Допустим у нас есть база в которой есть список документов, или чего-то там, и есть уникальное поле id, а также неуникальное поле parent_id. Если выбрать все элементы, то получится двумерны массив вида [id_xxx] => array("id", ..., "parent_id"). И с таким массивом может быть неудобно работать если вы захотите вывести вложенны список к приеру или как-то еще реализовать вложенность элементов. Для того чтобы решить эту проблему я предлагаю использовать нижеследующий скрипт:
Итак, вот такая у нас база:

И вот что мы хотим получить:

Для этого пишем код:
// Подключаемся к базе MYSQL
// Получаем из базы плоский массив (не буду это расписывать, т.к. у всех свои способы)
// Может быть у вас массив вообще не из MYSQL базы, а из CSV файла какого-нибудь..
class MyClassName {
public $cash = array();
public function getMaterialListTree(){
$query = $this->db->query("SELECT * FROM YourTable ORDER BY sort_order"); // Получаем как-то наш плоский массив
$this->cash['getMaterialList'] = $query; // И записываем его в кэш
$output = array();
foreach($this->cash['getMaterialList'] as $item){
if($item['parent_id'] == 0){ //Запускаем рекурсивную функцию только для паренотов самого высого уровня
$output[$item['id']] = $this->getMaterialListTree_get($item['id']);
}
}
return $output;
}
// Рекурсивная функция
public function getMaterialListTree_get($id = 0){
$output = array();
foreach($this->cash['getMaterialList'] as $k => $item){
if($item['id'] == $id){
// Записываем значение в возвращаемый массив
$output = $this->cash['getMaterialList'][$k];
// снова проходимся по нашему плоскому массиву в поисках документов у которых текущий числится родителем
foreach($this->cash['getMaterialList'] as $item_1){
if($item_1['parent_id'] == $id){
// если пока что массив для деток не создавался, создаем его
if(empty($output['children'])){
$output['children'] = array();
}
// если находим деток, то запускаем рекурсию дальше
$output['children'][$item_1['id']] = $this->getMaterialListTree_get($item_1['id']);
}
}
}
}
return $output;
}
}
// Печатаем как нам удобно:
$tree_elem = new MyClassName();
print_r($tree_elem->getMaterialListTree());
Еще один вариант для структурирования одномерного массива
Исходные данные те же самые, что и в первом примере. Но результат нужен такой:

Для этого пишем код:
class MyClassName {
public function getMaterialList(){
$input_array = $this->db->query("SELECT * FROM YourTable ORDER BY sort_order");
$material_list = array();
// Надо определить кто является парентом чтобы их не выводить
$material_parent_ids = array();
foreach($input_array as $elem){
$material_list[$elem['id']] = $elem;
}
foreach($material_list as $elem){
if(!in_array($elem['parent_id'] ,$material_parent_ids)){
$material_parent_ids[$elem['parent_id']] = $material_list[$elem['parent_id']]['id'];
}
}
$material_list_string = array();
foreach($material_list as $elem){
$temp_array = array();
// Тут нет рекурсии, но уж простите, в задаче не требовалось. Рекурсия выполнена в предыдущем примере.
if(!in_array($elem['id'],$material_parent_ids)){
$temp_array[] = $elem['material_name'];
if($elem['parent_id'] != 0){
$temp_array[] = $material_list[$elem['parent_id']]['material_name'];
}
if($material_list[$elem['parent_id']]['parent_id'] != 0){
$temp_array[] = $material_list[$material_list[$elem['parent_id']]['parent_id']]['material_name'];
}
$material_list_string[$elem['id']] = implode(" / ", array_reverse($temp_array));
}
}
asort($material_list_string);
return $material_list_string;
}
}
// Печатаем как нам удобно:
$tree_elem = new MyClassName();
print_r($tree_elem->getMaterialListTree());
Комментарии (0)
Не писать ответ