2010-08-21 12 views
1

je le code suivant (je sais que ce code n'est pas optimisé mais pas pour la discussion):Créer tableau de répertoires hiérarchiques en 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; 
} 

Fonction retourne ce tableau:

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) 
    ) 
) 

mais comment dois-je modifier le code

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

Pour fusionner array[3]-array[2][3] par exemple (parce que array[3] est un sous-répertoire de array[2] et array[2] est un sous-répertoire de array[0][2]), donc, je dois faire ce (quand je ne connais pas le niveau de sous-répertoires):

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

Je ne sais pas exactement comment vous déterminez ce qui est censé être un sous-répertoire de qui? Pouvez-vous expliquer cela un peu plus? – Chris

+0

Oui, bien sûr. J'ai la table avec des colonnes: 'id', 'name', 'parent'. Il y a aussi d'autres colonnes mais cela ne nous intéresse pas. Ainsi, 'parent' est la colonne qui contient 'id' de la catégorie parente pour la catégorie courante et est zéro si la catégorie est root. – purple

Répondre

1

En supposant que vous ne voulez pas les données/enfants Tags dans votre tableau:

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]; 

Si vous avez juste besoin de récupérer l'arbre complet de la base de données, vous pouvez même simplifier votre requête (obtenir tous les enregistrements à la fois) et supprimez l'appel récursif dans cette fonction. Vous aurez besoin d'une vérification supplémentaire qui ne définira que $ this-> tmp [$ catagory-> id] quand elle n'existe pas et qu'elle devrait fusionner les données avec les données existantes.

2

Longtemps J'ai écrit du code pour le faire en PHP. Il prend une liste d'entités (dans votre cas, catégories) et renvoie une structure où ces entités sont organisées dans un arbre. Cependant, il utilise des tableaux associatifs au lieu d'objets; il suppose que l'ID "parent" est stocké dans l'une des entrées du tableau associatif. Je suis sûr que vous pouvez adapter cela à vos besoins.

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; 
} 

Pour voir ce que cela fait, tout d'abord essayer d'exécuter sur une structure comme celle-ci:

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'); 

Si je ne me trompe pas, vous devriez obtenir quelque chose comme ceci: (le « clé parent » serait encore là, mais je le laisse pour plus de clarté)

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

Examinez le code pour voir comment il est ce que ca. Une fois que vous avez compris comment cela fonctionne, vous pouvez le modifier pour qu'il fonctionne avec vos données particulières.

+0

Oui, c'est ce que je veux je pense. – purple