2010-08-21 2 views
1

У меня есть следующий код (я знаю, что этот код не оптимизирован, но это не для обсуждения):Создание массива иерархических каталогов в PHP

function select_categories($cat_id) 
{ 
    $this->db = ORM::factory('category') 
      ->where('parent', '=', $cat_id) 
      ->find_all(); 

    foreach ($this->db as $num => $category) 
    { 
     if($category->parent == 0) 
     { 
      $this->tmp[$category->parent][$category->id] = array(); 
     } 
     else { 
      $this->tmp[$category->parent][$category->id] = array(); 
     } 

     $this->select_categories($category->id); 
    } 

    return $this->tmp; 
} 

Функция возвращает этот массив:

array(3) (
    0 => array(2) (
     1 => array(0) 
     2 => array(0) 
    ) 
    2 => array(1) (
     3 => array(0) 
    ) 
    3 => array(2) (
     4 => array(0) 
     5 => array(0) 
    ) 
) 

Но как я должен изменить код

else { 
    $this->tmp[$category->parent][$category->id] = array(); 
     // ^^^^^^^^^^^^^^^^^^^^^^ (this bit) 
} 

слить array[3] к array[2][3], например, (потому что array[3] является подкаталог array[2] и array[2] является подкаталог array[0][2]), поэтому мне нужно, чтобы сделать это (когда я не знаю, уровень подкаталогов):

array (
    0 => array (
     1 => array 
     2 => array (
        3 => array (
           4 => array 
           5 => array 
           ) 
        ) 
    ) 
) 
+0

Я не совсем уверен, как вы определяете, какой из них является подкаталогом? Не могли бы вы объяснить это немного больше? – Chris

+0

Да, конечно. У меня есть таблица со столбцами: 'id', 'name', 'parent'. Также есть несколько других столбцов, но мы этого не интересуем. Итак, «parent» - это столбец, который содержит «id» родительской категории для текущей категории и равен нулю, если категория является корнем. – purple

ответ

1

Предполагая, что вы не хотите, любые данные/дети теги в массиве:

foreach ($this->db as $num => $category) 
{ 
    // save the data to the array 
    $this->tmp[$category->id] = array(); 

    // save a reference to this item in the parent array 
    $this->tmp[$category->parent][$category->id] = &$this->tmp[$category->id]; 

    $this->select_categories($category->id); 
} 

// the tree is at index $cat_id 
return $this->tmp[$cat_id]; 

Если вам просто нужно, чтобы получить полное дерево из базы данных, вы можете даже упростить запрос (получить все записи сразу) и удалите рекурсивный вызов в этой функции. Вам понадобится дополнительная проверка, которая установит только $ this-> tmp [$ catagory-> id], если она не существует, и она должна объединить данные с существующими данными.

2

Долгое время назад Я написал код для этого в PHP. Он принимает список сущностей (в вашем случае, категории) и возвращает структуру, в которой эти объекты расположены в дереве. Однако он использует ассоциативные массивы вместо объектов; он предполагает, что «родительский» идентификатор хранится в одной из ассоциативных записей массива. Я уверен, что вы можете адаптировать это к вашим потребностям.

function make_tree_structure ($nontree, $parent_field) 
{ 
    $parent_to_children = array(); 
    $root_elements = array(); 

    foreach ($nontree as $id => $elem) { 
     if (array_key_exists ($elem[$parent_field], $nontree)) 
      $parent_to_children [ $elem[$parent_field] ][] = $id; 
     else 
      $root_elements[] = $id; 
    } 

    $result = array(); 
    while (count ($root_elements)) { 
     $id = array_shift ($root_elements); 
     $result [ $id ] = make_tree_structure_recurse ($id, $parent_to_children, $nontree); 
    } 
    return $result; 
} 

function make_tree_structure_recurse ($id, &$parent_to_children, &$nontree) 
{ 
    $ret = $nontree [ $id ]; 
    if (array_key_exists ($id, $parent_to_children)) { 
     $list_of_children = $parent_to_children [ $id ]; 
     unset ($parent_to_children[$id]); 
     while (count ($list_of_children)) { 
      $child = array_shift ($list_of_children); 
      $ret['children'][$child] = make_tree_structure_recurse ($child, $parent_to_children, $nontree); 
     } 
    } 
    return $ret; 
} 

Чтобы увидеть, что это делает, сначала попробуйте запустить его на структуру, как это:

var $data = array (
    0 => array('Name' => 'Kenny'), 
    1 => array('Name' => 'Lilo', 'Parent' => 0), 
    2 => array('Name' => 'Adrian', 'Parent' => 1) 
    3 => array('Name' => 'Mark', 'Parent' => 1) 
); 

var $tree = make_tree_structure($data, 'Parent'); 

Если я не ошибаюсь, вы должны получить что-то вроде этого из: (далее « родитель»ключ все еще будет там, но я оставляю это для ясности)

array (
    0 => array('Name' => 'Kenny', 'children' => array (
     1 => array('Name' => 'Lilo', 'children' => array (
      2 => array('Name' => 'Adrian') 
      3 => array('Name' => 'Mark') 
     ) 
    ) 
) 

Проверьте код, чтобы увидеть, как это Является ли это. Как только вы поймете, как это работает, вы можете настроить его для работы с вашими конкретными данными.

+0

Да, вот что я хочу, я думаю. – purple

Смежные вопросы