2010-03-03 2 views
2

J'essaie de récupérer des données hiérarchiques à partir d'une table mais je ne parviens pas à le faire. La table a (pour l'instant) les colonnes suivantes: ifc_key, ifc_name, ifc_parent. ifc_key n'est pas utilisé. (clé primaire, mais non utilisée pour cette fonctionFonction récursive PHP pour extraire des données hiérarchiques de la table plate (Zend Framework)

Le but est d'obtenir un tableau Chaque élément est une interface "parente" (donc tous ces éléments racine sont des valeurs ifc_name qui n'ont pas d'ensemble ifc_parent (ifc_name est égal si elle est définie)

Envisagez la mise en page suivante (démonstration):.

ifc_key | ifc_name | ifc_parent
0 | parent_ifc |
1 | A0A | parent_ifc
2 | a0b | parent_ifc
3 | b0a | vif1
4 | b0b | vif1
5 | vif1 | A0A

donc le tableau que je cherche, généré à partir d'une requête est:

Array 
(
[parent_ifc] => Array 
    (
     [a0a] => Array 
      (
       [vif1] => Array 
        (
         [0] => b0a 
         [1] => b0b 
        ) 

      ) 

     [a0b] => 
    ) 
) 

La fonction que je suis venu avec est sous ce paragraphe. Je voulais créer une fonction récursive, qui consiste à trouver des enfants, mais le problème est qu'aucun des enfants n'est sélectionné lors du premier appel à cette méthode. (ceux avec un parent vide sont les parents eux-mêmes). Donc, je récupère seulement les parents, mais aucun des enfants (et peut-être leurs enfants, etc. - cela peut en théorie être indéfini).

public static function getByFilerOrganisedChildren($filer_id, $parent = '') 
{ 
    $table = new Filer_Interface_Table(); 
    $where[] = $table->getAdapter()->quoteInto('ifc_system_id = ?', $filer_id); 
    $where[] = $table->getAdapter()->quoteInto('ifc_parent = ?', $parent); 
    $rows = $table->fetchAll($where, 'ifc_parent ASC'); 

    foreach ($rows as $row) { 
     if ($row->ifc_parent == '') $data[] = $row->ifc_name; 
     else { 
      $data[$row->ifc_parent][] = $row->ifc_name; 
      self::getByFilerOrganisedChildren($filer_id, $row->ifc_parent); 
     } 
    } 

    return (isset($data) ? $data : false); 
} 

Répondre

2

Vous n'avez fait aucune référence à la colonne ifc_system_id avant votre méthode donc je suppose que ce n'est pas immédiatement pertinent à la question. La sortie que vous spécifiez comme souhaitable est en fait incohérente. La clé qui vous manque, semble-t-il, est d'appeler la fonction récursive en utilisant des données pertinentes pour les enregistrements enfants - dans ce cas, ifc_name plutôt que .

public function getByFilerOrganisedChildren($filer_id, $parent = '') 
{ 
    $table = new Filer_Interface_Table(); 
    $where[] = $table->getAdapter()->quoteInto('ifc_system_id = ?', $filer_id); 
    $where[] = $table->getAdapter()->quoteInto('ifc_parent = ?', $parent); 
    $rows = $table->fetchAll($where, 'ifc_parent ASC'); 

    $data = array(); 
    foreach ($rows as $row) { 
     $data[$row->ifc_name] = $this->getByFilerOrganisedChildren($row->ifc_name); 
    } 

    return (! empty($data) ? $data : false); 
} 
0

Pouvez-vous écrire comment vous appelez cette fonction? avec quels sont les paramètres? Et je pense que vous devez faire des champs $ data statiques privés de votre classe

+0

$ interfaces = Filer_Interface :: getByFilerOrganisedChildren (filer- $> system_id); – Tom

0

Je ne réponds pas à votre question, mais: ce n'est pas très efficace pour stocker des données hiérarchiques dans la base de données.

Je préfère recommander l'ensemble imbriqué (par exemple, il existe des implémentations simples dans Doctrine ORM et Zend Framework [proposition]).

Vous pouvez également essayer une méthode alternative, décrite dans this article (qui est en polonais, mais les exemples SQL et PHP fournis sont universels).

+0

Salut, je sais que ce n'est pas le moyen le plus désiré de stocker ce type de données. Cependant, c'est pour une application existante qui lit les mails autosupport (Perl) et stocke ces données dans la base de données pour l'application. Tout ce qui était nécessaire maintenant est de construire une interface pour interroger ces données via le web. Donc, je dois travailler avec ce que j'ai. – Tom

0
public static function getByFilerOrganisedChildren($filer_id, $parent = '') 
{ 
    $table = new Filer_Interface_Table(); 
    $where[] = $table->getAdapter()->quoteInto('ifc_system_id = ?', $filer_id); 
    $where[] = $table->getAdapter()->quoteInto('ifc_parent = ?', $parent); 
    $rows = $table->fetchAll($where, 'ifc_parent ASC'); 

    foreach ($rows as $row) { 
     $data[$row->ifc_name] = array(); 
     /* self::getByFilerOrganisedChildren($filer_id, $row->ifc_name); */ 
    } 

    Zend_Debug::dump($data); 

    return (isset($this->data) ? $this->data : false); 
} 

Avec la ligne commentée ci-dessus, la sortie par Zend_Debug :: dump() est:

tableau

(7) {
[ "CIFS-80"] => array (0) {
}
[ "e0M"] => array (0) {
}
[ "lo"] => array (0) {
}
[ "VIF1"] => array (0) {}

[ "vif1-81"] => array (0) {}

[ "vif1-82"] => array (0) {}

[ "vif1-83" ] => array (0) {}

}

Ce sont tous les "parents". Mais comme attendu (puisque l'appel à la table est "ifc_parent = ''") aucun des enfants (et leurs enfants possibles) n'est retourné.

Cependant quand je décommentez la ligne:

self::getByFilerOrganisedChildren($filer_id, $row->ifc_name); 

La sortie est:

NULL 

Je pense qu'il est à cause de:

abstract class Filer_Interface_Abstract extends Filer_Db_Class 

Mais je suis incapable de changer cette - puisque c'est ainsi que l'application actuelle est construite. Suggestions?

0

Mon code

DB système:

create table roles (
    id  int not null auto_increment, 
    name varchar(50) UNIQUE not null, 
    inherit_id int 
) 

Code PHP:

class Default_Model_Roles extends Zend_Db_Table_Abstract { 

    protected $_parents = array(); 

    public function getParents($id) { 
     $this->_getAllParents($id); 
     return (! empty($this->parents) ? $this->parents : FALSE); 
    } 

    public function _getAllParents($id) { 
     $select = $this->select(); 
     $select->where('id = ?', $id) 
      ->order('id'); 
     $row = $this->fetchRow($select); 
     $this->parents[] = $row->id; 
     if ($row->inherit_id != NULL) 
      $this->_getAllParents($row->inherit_id); 
    } 
} 

Utilisation:

$table = new Default_Model_Roles(); 
$parents = $table->getParents($this->role_id); 
Questions connexes