Remplir un tableau parent/enfants recursivement

VaN
Mammouth du PHP | 1107 Messages

19 févr. 2010, 14:36

Bonjour,

j'ai une table de rubriques, que voici :
CREATE TABLE IF NOT EXISTS `cnje_documents_rubriques` (
  `rubrique_id` int(11) NOT NULL AUTO_INCREMENT,
  `rubrique_parent_id` int(11) DEFAULT NULL,
  `rubrique_nom` varchar(100) NOT NULL,
  `rubrique_statut` int(11) NOT NULL,
  PRIMARY KEY (`rubrique_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

--
-- Contenu de la table `cnje_documents_rubriques`
--

INSERT INTO `cnje_documents_rubriques` (`rubrique_id`, `rubrique_parent_id`, `rubrique_nom`, `rubrique_statut`) VALUES
(1, NULL, 'Documents administratifs', 1),
(2, NULL, 'Modèles', 1),
(3, 1, 'Cahiers de charges', 1),
(4, 1, 'Rapports d''activité', 1),
(5, 1, 'Visites Qualité', 1),
(6, 2, 'CV', 1),
(7, 2, 'Lettres de motivation', 1),
(8, 3, 'Test', 1);
J'aimerai, à partir d'un tableau stockant les rubriques parent de niveau 0 (donc celles avec un rubrique_parent_id valant 0), remplir mon tableau de rubriques avec leurs enfants, pour arriver au tableau suivant :
Array
(
    [0] => Array
        (
            [rubrique_id] => 1
            [rubrique_nom] => Documents administratifs
            [children] => Array
                (
                    [0] => Array
                        (
                            [rubrique_id] => 3
                            [rubrique_nom] => Cahiers de charges
                            [children] => Array
                                (
                                    [rubrique_id] => 8
                                    [rubrique_nom] => Test
                                )

                        )

                    [1] => Array
                        (
                            [rubrique_id] => 4
                            [rubrique_nom] => Rapports dactivité
                        )

                    [2] => Array
                        (
                            [rubrique_id] => 5
                            [rubrique_nom] => Visites Qualité
                        )

                )

        )

    [1] => Array
        (
            [rubrique_id] => 2
            [rubrique_nom] => Modèles
            [children] => Array
                (
                    [0] => Array
                        (
                            [rubrique_id] => 6
                            [rubrique_nom] => CV
                        )

                    [1] => Array
                        (
                            [rubrique_id] => 7
                            [rubrique_nom] => Lettres de motivation
                        )

                )

        )

)
Voici la fonction qui va chercher les parents de niveau 0 :
function get_documents_rubriques() {
	global $config, $tables;
	
	$documents_rubriques = get_array_from_query("SELECT rubrique_id, rubrique_nom
	FROM ".$tables["documents_rubriques"]." 
	WHERE rubrique_parent_id IS NULL AND rubrique_statut = 1");
	
	$documents_rubriques = fill_array_with_children($documents_rubriques, $tables["documents_rubriques"], array("id" => "rubrique_id", "parent" => "rubrique_parent_id", "statut" => "rubrique_statut"), array("rubrique_id", "rubrique_nom"));
	
	return $documents_rubriques;
}
Et la fonction recursive censée remplir un tableau avec ses enfants :
// Remplie un tableau avec ses enfants, et retourne ce tableau
function fill_array_with_children($array, $table, $conditions_fields, $selected_fields, $level = 0) {
	global $config, $tables;
	$level++;
	
	$selected_fields_sql = concat_field($selected_fields);
	
	foreach($array as $key => $row) {
		$children = get_array_from_query(sprintf("SELECT ".$selected_fields_sql." FROM ".$table." 
		WHERE ".$conditions_fields["parent"]." = '%d' AND ".$conditions_fields["statut"]." = 1", $row[$conditions_fields["id"]]), true);
		
		print_r_pre($children);
		
		if(!empty($children)) {
			foreach($children as $key_child => $child) {
				$children[$key_child]["children"] = fill_array_with_children($child, $table, $conditions_fields, $selected_fields, $level);
			}
			$array[$key]["children"] = $children;
		}
	}
	echo "<hr />";
	
	
	return $array;
}
Mais actuellement, cela ne fonctionne pas. Voici ce que j'obtiens :
Array
(
    [0] => Array
        (
            [rubrique_id] => 1
            [rubrique_nom] => Documents administratifs
            [children] => Array
                (
                    [0] => Array
                        (
                            [rubrique_id] => 3
                            [rubrique_nom] => Cahiers de charges
                            [children] => Array
                                (
                                    [rubrique_id] => A
                                    [rubrique_nom] => Cahiers de charges
                                )

                        )

                    [1] => Array
                        (
                            [rubrique_id] => 4
                            [rubrique_nom] => Rapports d activité
                            [children] => Array
                                (
                                    [rubrique_id] => 4
                                    [rubrique_nom] => Rapports d activité
                                )

                        )

                    [2] => Array
                        (
                            [rubrique_id] => 5
                            [rubrique_nom] => Visites Qualité
                            [children] => Array
                                (
                                    [rubrique_id] => 5
                                    [rubrique_nom] => Visites Qualité
                                )

                        )

                )

        )

    [1] => Array
        (
            [rubrique_id] => 2
            [rubrique_nom] => Modèles
            [children] => Array
                (
                    [0] => Array
                        (
                            [rubrique_id] => 6
                            [rubrique_nom] => CV
                            [children] => Array
                                (
                                    [rubrique_id] => 6
                                    [rubrique_nom] => CV
                                )

                        )

                    [1] => Array
                        (
                            [rubrique_id] => 7
                            [rubrique_nom] => Lettres de motivation
                            [children] => Array
                                (
                                    [rubrique_id] => 7
                                    [rubrique_nom] => Lettres de motivation
                                )

                        )

                )

        )

)
Une âme charitable pourrai-elle m'aider à debugger cette fonction ?

ViPHP
AB
ViPHP | 5818 Messages

19 févr. 2010, 18:28

Heu.. à priori il serait plus simple de faire une seule requête avec jointure pour ramener tout en une seule fois. N'est-ce pas possible ?

VaN
Mammouth du PHP | 1107 Messages

19 févr. 2010, 19:42

Aucune idée. Est-ce possible d'avoir en retour un tableau multi-level avec les enfants stockés dans leurs parents ?

VaN
Mammouth du PHP | 1107 Messages

27 févr. 2010, 01:46

Hop, remontage de fil, car j'ai un nouveau souci.

Tout d'abord, j'ai réussi à peupler mon tableau d'éléments parents avec leur enfants, de manière récursive, comme ceci :
// Remplie un tableau avec ses enfants, et retourne ce tableau
function fill_array_with_children($array, $table, $conditions_fields, $selected_fields, $level = 0) {
	global $config, $tables;
	$level++;
	//print_r_pre($array);
	$selected_fields_sql = concat_field($selected_fields);
	
	foreach($array as $key => $row) {

		$children = get_array_from_query(sprintf("SELECT ".$selected_fields_sql." FROM ".$table." 
		WHERE ".$conditions_fields["parent"]." = '%d' AND ".$conditions_fields["statut"]." = 1", $row[$conditions_fields["id"]]), true);
		
		if(!empty($children)) {
			//print_r_pre($children, "red");
			foreach($children as $key_child => $child) {
			
				$child = fill_array_with_children($children, $table, $conditions_fields, $selected_fields, $level);
				$array[$key]["children"] = $child;
			}
		}	
	}
	
	return $array;
}
Mon nouveau problème est le suivant :

J'ai également une table de documents, que je lie à une rubrique, grâce à un champ document_rubrique_id.

J'aimerai pour chacun de mes éléments de mon tableau de rubriques, récupérer le nombre de documents associés. La difficulté est que le nombre de documents d'une rubrique "mère" doit être la somme de ses propres documents et de tous les documents de ses rubriques filles.

Voila le tableau que j'aimerai avoir au final :
Array
(
    [0] => Array
        (
            [rubrique_id] => 1
            [rubrique_nom] => Documents administratifs
            [documents] => Array
                (
                    [0] => Array
                        (
                            [document_id] => 1
                            [document_date] => 2010-02-26
                            [document_file] => Lisez-moi.txt
                            [document_description] => 
                            [document_telechargements] => 3
                            [document_statut] => 1
                        )

                )

            [children] => Array
                (
                    [0] => Array
                        (
                            [rubrique_id] => 3
                            [rubrique_nom] => Cahiers de charges
                            [documents] => Array
                                (
                                    [0] => Array
                                        (
                                            [document_id] => 2
                                            [document_date] => 2010-02-26
                                            [document_file] => Lisez-moi2.txt
                                            [document_description] => 
                                            [document_telechargements] => 3
                                            [document_statut] => 1
                                        )

                                )

                            [nb_documents] => 1
                        )

                    [1] => Array
                        (
                            [rubrique_id] => 4
                            [rubrique_nom] => Rapports dactivité
                            [nb_documents] => 0
                        )

                    [2] => Array
                        (
                            [rubrique_id] => 5
                            [rubrique_nom] => Visites Qualité
                            [nb_documents] => 0
                        )

                )

            [nb_documents] => 2
        )
)
Bref, comment puis-je récupérer le nombre totaux de documents d'une rubrique ?