2010-02-28 12 views
2

J'ai une fonction qui obtient les identifiants de tous les enfants d'un parent de ma base de données. Donc, si je cherchais l'id 7, il pourrait retourner un tableau avec 5, 6 et 10. Ce que je veux faire, c'est trouver récursivement les enfants de ces ids retournés, et ainsi de suite, à la profondeur finale des enfants.PHP: Obtenir récursivement les enfants du parent

J'ai essayé d'écrire une fonction pour ce faire, mais je suis confus au sujet de la récursivité.

function getChildren($parent_id) { 
    $tree = Array(); 
    $tree_string; 
    if (!empty($parent_id)) { 
     // getOneLevel() returns a one-dimentional array of child ids 
     $tree = $this->getOneLevel($parent_id); 
     foreach ($tree as $key => $val) { 
      $ids = $this->getChildren($val); 
      array_push($tree, $ids); 
      //$tree[] = $this->getChildren($val); 
      $tree_string .= implode(',', $tree); 
     } 

     return $tree_string; 
    } else { 
     return $tree; 
    } 

}//end getChildren() 

Une fois la fonction est exécutée, je voudrais revenir à un tableau à une dimentionnelle de tous les enfants ids qui ont été trouvés.

Répondre

3

Nested Set modèle au lieu de contiguïté Liste modèle


Puis-je suggérer que vous stockez vos noeuds dans votre base de données sous NSM au lieu de ALM? Notez qu'avec ALM, (ce qui est ce que vous utilisez) obtenir les nœuds enfants est assez difficile, c'est possible, mais nécessite un travail supplémentaire. Si vous utilisez un modèle d'ensemble imbriqué en sélectionnant un nœud enfant ou tous les nœuds, ou même en recherchant la profondeur de tous les nœuds, vous pouvez le faire dans une seule requête SQL.

J'espère que cela éclaircira la façon dont vous pourriez résoudre votre problème, si vous êtes encore jeune dans le développement de votre projet de commutation maintenant vous permettra d'économiser beaucoup de maux de tête plus tard.

+0

Avec le modèle de liste d'adjacence, est-il facile de mettre à jour/déplacer le parent? –

+0

Non, il faut pas mal de requêtes pour mettre à jour les tables ALM. Environ6 ~ en fonction de la façon dont vous pouvez optimiser vos requêtes. Les avantages sont tous faits lorsque vous sélectionnez. Alors plutôt que de faire 4 requêtes en sélectionnant la profondeur, les enfants, les parents etc, vous pouvez le faire juste une requête. Donc, si vous sélectionnez plus que vous insérez et mettez à jour, vous devez utiliser ALM imho. – Layke

+0

N'est-ce pas l'inverse? Avec les ensembles imbriqués, il est facile de récupérer l'arbre complet (ou n'importe quel sous-ensemble de l'arbre), en sélectionnant et en triant les valeurs de gauche associées à chaque noeud. Reportez-vous à http://dev.mysql.com/tech-resources/articles/hierarchical-data.html pour plus d'informations (spécifique à MySQL, mais devrait être facilement portable vers un autre SGBDR si nécessaire). – wimvds

5

Ce beau travail pour moi:

function getOneLevel($catId){ 
    $query=mysql_query("SELECT categoryId FROM categories WHERE categoryMasterId='".$catId."'"); 
    $cat_id=array(); 
    if(mysql_num_rows($query)>0){ 
     while($result=mysql_fetch_assoc($query)){ 
      $cat_id[]=$result['categoryId']; 
     } 
    } 
    return $cat_id; 
} 

function getChildren($parent_id, $tree_string=array()) { 
    $tree = array(); 
    // getOneLevel() returns a one-dimensional array of child ids   
    $tree = $this->getOneLevel($parent_id);  
    if(count($tree)>0 && is_array($tree)){  
     $tree_string=array_merge($tree_string,$tree); 
    } 
    foreach ($tree as $key => $val) { 
     $this->getChildren($val, &$tree_string); 
    } 
    return $tree_string; 
} 

Appelez le getChildren(yourid); Ensuite, il retourne le tableau complet des enfants pour ce noeud/parent donné.

+0

C'est bien. Vous devez envelopper les deux en classe probablement. Aussi j'ai inséré le code ci-dessous à droite 'après $ arbre = $ this-> getOneLevel ($ parent_id);' 'foreach ($ arbre comme $ branch => $ branche_branche) { if (in_array ($ branche_branche, $ chaîne_ligne)) { unset ($ tree [$ branch]); } } ' Cela ne semble pas correct, comment puis-je commenter avec un exemple de code? – henrijs

0

Plutôt que array_push($tree, $ids); essayez $tree = array_merge($tree, $ids);. Tuez le $tree_string .= implode(',', $tree); et juste return $tree. (Une fois)

function getChildren($parent_id) { 
    $tree = Array(); 
    if (!empty($parent_id)) { 
     $tree = $this->getOneLevel($parent_id); 
     foreach ($tree as $key => $val) { 
      $ids = $this->getChildren($val); 
      a$tree = array_merge($tree, $ids); 
     } 
    } 
    return $tree; 
}