Или можно перефразировать задачу — Как получить многомерный массив из одномерного (плоского), или Получить вложенный массив из одномерного.
Допустим у нас есть база в которой есть список документов, или чего-то там, и есть уникальное поле 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)
Не писать ответ