Republié par Joy Murakami, j'ai déjà lu cet article et il est expliqué assez clairement.
Nous rencontrerons ce problème dans de nombreux endroits tels que la classification des produits, les forums arborescents multi-niveaux, les listes de diffusion, etc. : Comment stocker des données structurées multi-niveaux ?
Dans les applications PHP, le stockage des données back-end est généralement une base de données relationnelle, qui peut enregistrer de grandes quantités de données et fournir des services efficaces de récupération et de mise à jour des données. Cependant, la forme de base des données relationnelles est une table entrecroisée, qui est une structure plate. Si vous souhaitez stocker une structure arborescente à plusieurs niveaux dans une base de données relationnelle, vous devez effectuer un travail de traduction raisonnable. Ensuite, je discuterai avec vous de ce que j'ai vu et entendu ainsi que de quelques expériences pratiques.
Il existe essentiellement deux méthodes de conception courantes pour stocker des données hiérarchiques dans des bases de données plates :
le modèle de liste de contiguïté
Algorithme de traversée de l'arbre de précommande modifié
Je ne suis pas un spécialiste en informatique et je n'ai rien appris sur les structures de données, j'ai donc traduit ces deux noms littéralement. Veuillez me faire savoir si je me trompe.
Ces deux choses peuvent paraître effrayantes, mais elles sont en réalité très faciles à comprendre. Ici, j'utilise un simple répertoire d'aliments comme exemple de données. Notre structure de données est la suivante :
Nourriture
|
|---Fruits
|
|---Rouge
|
|--Cerise
|
|---Jaune
|
|--Banane
|
|---Viande
|
|--Bœuf
|
|--Porc
Afin de prendre soin des passionnés de PHP qui ont un gâchis en anglais
Food : Food
Fruits : fruits
Rouge : rouge
Cerise : cerise
Jaune : jaune
Banane : banane
Viande : Viande
Bœuf : bœuf
Porc :
Le modèle de liste de contiguïté
du porcest un modèle que nous utilisons souvent et qui a été présenté dans de nombreux didacticiels et livres. Nous décrivons l'ensemble de l'arborescence à travers un tableau plat en ajoutant un attribut parent à chaque nœud pour représenter le nœud parent de ce nœud. Selon ce principe, les données de l'exemple peuvent être transformées dans le tableau suivant :
+-----------------------+
| nom du parent |
+-----------------------+
| Alimentation |
| Alimentation | Fruits |
| Fruits | Vert |
| Vert | Poire
| Fruits Rouge |
| Rouge Cerise |
| Fruits | Jaune |
Jaune | Banane |
| Alimentation | Viande |
Viande |
Viande | Porc |
+-----------------------+
Nous voyons que Pear est un nœud enfant de Green et que Green est un nœud enfant de Fruit. Le nœud racine « Food » n'a pas de nœud parent. Afin de décrire simplement ce problème, seul le nom est utilisé pour représenter un enregistrement dans cet exemple. Dans une base de données réelle, vous devez utiliser un identifiant numérique pour identifier chaque nœud. La structure de la table de la base de données devrait probablement ressembler à ceci : id, parent_id, name, description. Avec une telle table, nous pouvons sauvegarder l’intégralité de l’arborescence à plusieurs niveaux via la base de données.
Afficher un arbre multi-niveaux Si nous devons afficher une telle structure multi-niveaux, nous avons besoin d'une fonction récursive.
<?php
// $parent est le parent des enfants que nous voulons voir
// Le niveau $ augmente lorsque l'on s'enfonce plus profondément dans l'arbre,
// utilisé pour afficher une jolie
fonction d'arbre en retrait display_children($parent, $level)
{
// Récupère tous les nœuds enfants d'un nœud parent $parent
$result = mysql_query('SELECT nom FROM tree '.
'WHERE parent="'.$parent.'";');
// Afficher chaque nœud enfant
tandis que ($row = mysql_fetch_array($result))
{
// Indente le nom du nœud
echo str_repeat(' ',$level).$row['name']."n"
//Appelle à nouveau cette fonction pour afficher les nœuds enfants du nœud enfant
display_children($row['name'], $level+ 1);
}
}
?>
L'utilisation de cette fonction sur le nœud racine (Food) de la structure entière peut imprimer l'intégralité de l'arborescence à plusieurs niveaux. Puisque Food est le nœud racine et que son nœud parent est vide, appelez : display_children('',0). affichera le contenu de l'arborescence entière :
Nourriture
Fruit
Rouge
Cerise
Jaune
Banane
Viande
Bœuf
Porc
Si vous souhaitez afficher seulement une partie de la structure entière, comme la partie fruit, vous pouvez l'appeler comme ceci :
display_children('Fruit',0);
Presque en utilisant la même méthode, nous pouvons connaître le chemin depuis le nœud racine. à n’importe quel nœud. Par exemple, le chemin de Cherry est « Alimentation > Fruit > Rouge ». Pour obtenir un tel chemin, nous devons partir du niveau le plus profond "Cherry", interroger pour obtenir son nœud parent "Red" et l'ajouter au chemin, puis nous interrogeons le nœud parent de Red et l'ajoutons au chemin. , et ainsi de suite jusqu'au niveau supérieur "Food"
<?php
// $node est le nœud le plus profond
fonction get_path($node)
{
// Interroge le nœud parent de ce nœud
$result = mysql_query('SELECT parent FROM tree'.
'WHERE nom="'.$node.'";');
$row = mysql_fetch_array($result);
// Utiliser un tableau pour enregistrer le chemin
$path = array();
// S'il ne s'agit pas du nœud racine, continuez à interroger vers le haut
// (Le nœud racine n'a pas de nœud parent)
si ($row['parent']!='')
{
// la dernière partie du chemin vers $node est le nom
// du parent de $node
$path[] = $row['parent'];
// nous devrions ajouter le chemin au parent de ce nœud
// vers le chemin
$path = array_merge(get_path($row['parent']), $path);
}
// renvoie le chemin
retourner $chemin ;
}
?>
Si vous utilisez cette fonction pour "Cherry" : print_r(get_path('Cherry')), vous obtiendrez un tableau comme celui-ci :
Tableau
(
[0] => Nourriture
[1] => Fruits
[2] => Rouge
)
C'est à vous de décider comment l'imprimer dans le format souhaité.
Inconvénients : Cette méthode est très simple, facile à comprendre et à utiliser. Mais il y a quelques inconvénients. Principalement parce que la vitesse d'exécution est très lente, parce que chaque nœud nécessite une requête de base de données, et lorsque la quantité de données est importante, de nombreuses requêtes sont nécessaires pour compléter une arborescence. De plus, en raison de la nécessité d'opérations récursives, chaque niveau de récursion doit occuper une certaine mémoire, de sorte que l'efficacité d'utilisation de l'espace est relativement faible.
Jetons maintenant un coup d'œil à une autre méthode qui n'utilise pas de calculs récursifs et qui est plus rapide. Il s'agit de l'algorithme de traversée d'arbre de précommande modifié. Vous serez peut-être moins exposé à cette méthode, et elle n'est pas comme celle ci-dessus lorsque vous l'utilisez. la première fois. La méthode est facile à comprendre, mais comme elle n'utilise pas d'algorithmes de requête récursifs, elle a une efficacité de requête plus élevée.
Nous dessinons d'abord les données multi-niveaux sur papier de la manière suivante, écrivons 1 sur le côté gauche du nœud racine Food, puis continuons vers le bas de l'arbre, écrivons 2 sur le côté gauche de Fruit, puis continuons à nous déplacer le long de l'arbre entier. . Les bords étiquettent chaque nœud avec des numéros à gauche et à droite. Le dernier chiffre est le 18 marqué à droite de Food. Dans l'image ci-dessous, vous pouvez voir l'intégralité de la structure à plusieurs niveaux marquée par des chiffres. (Vous ne comprenez pas ? Montrez les chiffres avec vos doigts et comptez de 1 à 18 et vous comprendrez. Si vous ne comprenez toujours pas, comptez à nouveau et faites attention à bouger vos doigts).
Ces nombres indiquent la relation entre chaque nœud. Les nombres de « Rouge » sont 3 et 6, qui sont les nœuds descendants de « Nourriture » 1-18. De même, nous pouvons voir que tous les nœuds avec une valeur à gauche supérieure à 2 et une valeur à droite inférieure à 11 sont des descendants de "Fruit" 2-11.
1 Nourriture 18
|
+--------------------------------------------------+
|
2 Fruits 11 12 Viande 17
|
+---------------------+ +---------------------+
|
3 Rouge 6 7 Jaune 10 13 Bœuf 14 15 Porc 16
|
4 Cherry 5 8 Banana 9
De cette façon, toute la structure arborescente peut être stockée dans la base de données via les valeurs gauche et droite. Avant de continuer, jetons un coup d'œil au tableau de données compilé ci-dessous.
+-----------------------+-----+-----+
| nom du parent |
+-----------------------+-----+-----+
| Alimentation | 1 |
| Nourriture | Fruits 2 |
| Fruits | Rouge | 3 |
| Rouge | Cerise 4 |
| Fruits | Jaune | 7 |
| Jaune | Banane |
| Alimentation | Viande | 12 |
Viande |
Viande | Porc 15 |
+-----------------------+-----+-----+
Remarque : Puisque « gauche » et « droite » ont des significations particulières en SQL, nous devons utiliser « lft » et « rgt » pour représenter les champs gauche et droit. De plus, le champ « parent » n’est plus nécessaire dans cette structure pour représenter l’arborescence. En d’autres termes, la structure de tableau suivante est suffisante.
+------------+-----+-----+
| nom |
+------------+-----+-----+
| Alimentation | 1 | 18 |
| Fruits | 2 | 11 |
| Rouge | 3 | 6 |
| Cerise | 4 |
| Jaune | 7 |
| Banane | 8 |
| Viande | 12 |
Bœuf | 13 |
Porc |
+------------+-----+-----+
Bon, nous pouvons maintenant récupérer les données de la base de données. Par exemple, si nous avons besoin d'obtenir tous les nœuds sous l'élément "Fruit", nous pouvons écrire l'instruction de requête comme ceci : SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ; la requête a obtenu les résultats suivants.
+------------+-----+-----+
| nom |
+------------+-----+-----+
| Fruits | 2 | 11 |
| Rouge | 3 | 6 |
| Cerise | 4 |
| Jaune | 7 |
| Banane | 8 |
+------------+-----+-----+
Vous voyez, vous pouvez obtenir tous ces nœuds avec une seule requête. Afin de pouvoir afficher l'intégralité de l'arborescence comme la fonction récursive ci-dessus, nous devons également trier une telle requête. Trier par la valeur l du nœud :
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;
La question restante est de savoir comment afficher l'indentation hiérarchique.
<?php
fonction display_tree ($root)
{
//Obtenir les valeurs gauche et droite du nœud racine
$result = mysql_query('SELECT lft, rgt FROM tree '.'WHERE name="'.$root.'";');
$row = mysql_fetch_array($result);
// Préparez une pile rvalue vide
$right = array();
// Récupère tous les nœuds descendants du point racine
$result = mysql_query('SELECT nom, lft, rgt FROM arborescence '.
'OÙ lft ENTRE '.$row['lft'].'
$row['rgt'].' ORDER BY lft ASC;');
// Afficher chaque ligne
tandis que ($row = mysql_fetch_array($result))
{
// vérifie la pile uniquement s'il y en a une
si (compte($droit)>0)
{
// Vérifie si nous devons déplacer le nœud hors de la pile
while ($right[count($right)-1]<$row['rgt'])
{
array_pop($à droite);
}
}
// Indente le nom du nœud.
echo str_repeat(' ',count($right)).$row['name']."n"
// Ajoute ce nœud à la pile;
$right[] = $row['rgt'];
}
}
?>
Si vous exécutez la fonction ci-dessus, vous obtiendrez le même résultat que la fonction récursive. C'est juste que notre nouvelle fonction est peut-être plus rapide car il n'y a que 2 requêtes de base de données. Il est plus facile de connaître le chemin d'un nœud. Si l'on veut connaître le chemin de Cherry, on utilise ses valeurs gauche et droite 4 et 5 pour faire une requête.
SELECT nom FROM arbre WHERE lft < 4 AND rgt > 5 ORDER BY lft ASC;
Cela vous donnera le résultat suivant :
+----------------++
| nom |
+----------------+
Alimentation |
Fruits |
| Rouge |
+----------------+
Alors, combien de nœuds descendants possède un certain nœud ? C'est très simple, le nombre total de descendants = (rvalue - valeur gauche - 1)/2 descendants = (droite - gauche - 1) / 2 Vous n'y croyez pas ? Faites le calcul vous-même. En utilisant cette formule simple, nous pouvons calculer rapidement que le nœud « Fruit 2-11 » a 4 nœuds descendants, tandis que le nœud « Banane 8-9 » n'a pas de nœuds descendants, ce qui signifie qu'il ne s'agit pas d'un nœud parent.
Incroyable, non ? Même si j’ai utilisé cette méthode à plusieurs reprises, c’est toujours une sensation incroyable à chaque fois que je la pratique.
C'est en effet une bonne méthode, mais existe-t-il un moyen de nous aider à créer un tel tableau de données avec des valeurs gauche et droite ? Voici une autre fonction à vous présenter. Cette fonction peut convertir automatiquement la table avec le nom et les structures parentes en une table de données avec des valeurs gauche et droite.
<?php
fonction reconstruire_tree($parent, $left) {
// la valeur droite de ce nœud est la valeur gauche + 1
$right = $left+1;
// récupère tous les enfants de ce nœud
$result = mysql_query('SELECT nom FROM tree '.
'WHERE parent="'.$parent.'";');
while ($row = mysql_fetch_array($result)) {
// exécution récursive de cette fonction pour chaque
// enfant de ce nœud
// $right est la bonne valeur actuelle, qui est
// incrémenté par la fonction reconstruction_tree
$right = reconstruire_tree($row['name'], $right);
}
// nous avons la valeur gauche, et maintenant que nous avons traité
// les enfants de ce nœud on connaît aussi la bonne valeur
mysql_query('UPDATE tree SET lft='.$left.', rgt='.
$right.' WHERE name="'.$parent.'";');
// renvoie la bonne valeur de ce nœud + 1
retourner $droit+1 ;
}
?>
Bien sûr, cette fonction est une fonction récursive. Nous devons exécuter cette fonction à partir du nœud racine pour reconstruire un arbre avec les valeurs gauche et droite
rebuild_tree('Food',1);
Cette fonction semble un peu compliquée, mais sa fonction est la même que la numérotation manuelle du tableau, qui consiste à convertir la structure multicouche tridimensionnelle en un tableau de données avec des valeurs gauche et droite.
Alors, comment ajouter, mettre à jour et supprimer un nœud pour une telle structure ? Il existe généralement deux manières d'ajouter un nœud :
conserver le nom d'origine et la structure parent, utiliser l'ancienne méthode pour ajouter des données aux données et utiliser la fonction reconstruction_tree pour renuméroter la structure entière après l'ajout de chaque élément de données.
Une approche plus efficace consiste à modifier toutes les valeurs à droite du nouveau nœud. Par exemple : nous souhaitons ajouter un nouveau fruit « Fraise » qui deviendra le dernier nœud enfant du nœud « Rouge ». Nous devons d’abord lui faire de la place. La valeur droite de « Rouge » doit être modifiée de 6 à 8, et les valeurs gauche et droite de « Jaune 7-10 » doivent être modifiées à 9-12. Par analogie, on peut savoir que si l'on veut faire de la place à de nouvelles valeurs, il faut ajouter 2 à tous les nœuds ayant des valeurs gauche et droite supérieures à 5 (5 est la valeur droite du dernier nœud enfant de "Rouge" ). Nous effectuons donc des opérations de base de données comme ceci :
UPDATE tree SET rgt=rgt+2 WHERE rgt>5;
Arbre UPDATE SET lft=lft+2 WHERE lft>5;
Cela libère de l'espace pour la valeur nouvellement insérée. Vous pouvez maintenant créer un nouveau nœud de données dans l'espace libéré. Ses valeurs gauche et droite sont respectivement 6 et 7
INSERT INTO tree SET lft=6, rgt=7, name =. « Fraise » ;
Faisons une autre requête et voyons ! Et ça ? Bientôt.
D'accord, vous pouvez maintenant concevoir votre structure de base de données multi-niveaux de deux manières différentes. La méthode que vous utilisez dépend entièrement de votre jugement personnel, mais pour les structures comportant plusieurs niveaux et un grand nombre, je préfère la deuxième méthode. La première méthode est plus simple si le volume de requêtes est faible, mais les données doivent être ajoutées et mises à jour fréquemment.
De plus, si la base de données le prend en charge, vous pouvez également écrire reconstruction_tree() et l'opération de libération d'espace comme fonction de déclenchement côté base de données, et l'exécuter automatiquement lors de l'insertion et de la mise à jour. Cela peut obtenir une meilleure efficacité opérationnelle, et vous pouvez. ajouter de nouveaux nœuds. Les instructions SQL deviendront plus simples.
Méthode récursive de classe
Publié par un invité le 31 mai 2004 à 9h18.
J'ai écrit un programme en utilisant une méthode quasi-récursive, qui n'est pas exactement la même que la récursivité de l'article, et je m'apprête à le transplanter dans xoops :
http://dev.xoops.org/modules/xfmod/project/?ulink
a connu un débordement de mémoire, mais je prévois de continuer à utiliser la méthode récursive. J'ai juste besoin de continuer à m'améliorer,
j'espère avoir l'occasion d'en discuter
.cms avec toi.
» répondre à ce commentaire
Ou une comparaison des deux méthodes ?
Publié par un invité le 17 mars 2004 à 20h30.
J'ai étudié cet article attentivement et j'ai senti qu'il était très bénéfique, mais j'y ai ensuite repensé et j'ai senti qu'il y avait un problème (pour des raisons de mémoire, j'appelle le mode répertoire adjacent la méthode récursive, et le parcours de pré-tri algorithme d'arbre que j'appelle la méthode de l'arbre de pré-tri) :
1. La plus grande différence entre les deux méthodes est que la récursivité nécessite l'utilisation d'une pile lors de l'interrogation, tandis que l'arbre de pré-tri nécessite la moitié des nœuds (en référence à la seconde moitié de le nœud inséré) lors de la mise à jour des nœuds de mises à jour. Bien que vous ayez également dit que s'il y a de nombreux nœuds et des mises à jour fréquentes, l'efficacité de l'arborescence pré-triée sera réduite et la récursion sera meilleure s'il y a plusieurs niveaux de nœuds, tout d'abord, la récursivité provoquera un débordement de pile et. de plus, la récursivité elle-même n'est pas très efficace, et chaque niveau de récursion nécessite l'exploitation de la base de données, l'effet global ne sera pas idéal. Mon approche actuelle consiste à supprimer toutes les données en même temps, puis à effectuer des opérations récursives sur le tableau, ce qui sera préférable si cela peut être encore amélioré, un nœud racine ROOT peut être ajouté à chaque ligne d'enregistrements (actuellement, uniquement). les nœuds parents adjacents sont enregistrés), de sorte que l'efficacité lors de la recherche dans l'arborescence des branches soit plus élevée, et cela sera également très pratique lors de la mise à jour de l'arborescence, ce qui devrait être une meilleure solution.
2. Améliorer la méthode récursive.Dans l'article, lors du calcul des valeurs gauche et droite des nœuds d'arbre pré-triés, une méthode de parcours est en fait utilisée. La pile est remplacée par un tableau, et le push et le pop. sont implémentés manuellement ; si cette méthode est référencée dans l'algorithme récursif, si vous utilisez un tableau au lieu de la pile lors de l'exécution de la récursivité, vous pouvez également améliorer l'efficacité de la récursivité.
3. Concurrence. Si la concurrence est prise en compte, en particulier lors de la mise à jour de l'arborescence, la méthode de mise à jour des informations sur les nœuds dans une grande zone de l'arborescence pré-triée nécessite une attention particulière à l'utilisation de mécanismes de verrouillage et de transaction pour garantir cohérence des données.
4. Dans le cas de plusieurs nœuds racines ou de plusieurs nœuds parents, dans ce cas, il ne s'agit évidemment pas d'un arbre binaire standard ou d'un arbre multi-fork. L'algorithme de l'arbre pré-trié doit être considérablement amélioré pour s'adapter, et la méthode récursive. est appliqué librement, donc dans ce cas, la récursivité est plus adaptable. Ceci est bien sûr dû au fait que la méthode récursive est une forme de liste chaînée. Les arbres et les graphiques peuvent être exprimés par des listes chaînées, et bien sûr, elle est hautement adaptable.
5. Intuitif. Si vous observez directement les données stockées dans la base de données sans opération de programme, il est évident que les données stockées en mode récursif sont plus intuitives, tandis que les données dans l'arborescence pré-triée sont difficiles à lire directement (pour les données hiérarchiques). relations). Ceci est important dans l’échange de données. Cela aura-t-il un impact ?
D'une manière générale, je préfère personnellement utiliser des méthodes récursives, mais j'ai toujours été inquiet de l'impact de la récursivité sur l'efficacité. Heureusement, je n'ai pas été exposé à des niveaux de classification à grande échelle. L'utilisation récursive de tableaux au lieu de piles serait une meilleure amélioration. méthode. L'arbre pré-trié est une méthode efficace pour résoudre des arbres simples. Une fois que vous vous y êtes habitué, il devrait être très bon, en particulier sa recherche inverse du nœud feuille au nœud racine est très pratique.
Loup
www.fwolf.com
» répondre à ce commentaire
Très heureux de voir votre réponse
Publié par shuke le 18 mars 2004 - 5h47.
Je suis très heureux que vous ayez lu cet article si attentivement. Cet article a en fait été initialement publié sur sitepoint.com. Je l'ai traduit, dans l'espoir de présenter quelques méthodes à des amis qui souhaitent se lancer. Votre méthode est également très bonne, je l'essaierai si j'en ai l'occasion. (Si vous êtes intéressé, pourquoi ne pas écrire votre méthode et votre code d'implémentation spécifique sous forme de tutoriel basé sur l'exemple ci-dessus, afin que tout le monde puisse l'imiter avec des exemples plus pratiques) Si vous avez des questions sur la sauvegarde des structures multi-niveaux dans la base de données Si vous êtes intéressés par la recherche, voici deux autres bons liens qui peuvent être utilisés comme référence :
Présentation des quatre méthodes courantes de script de requête unique et de tri de tableaux. Je pense que votre script doit être meilleur que cela.
De plus, j'ai vu que vous utilisez également Drupal. Il dispose également d'une fonctionnalité avancée appelée système d'authentification d'utilisateur distribué. Tant que vous vous inscrivez sur n'importe quel site Drupal, vous pouvez vous connecter pour accéder à d'autres sites Drupal. Assez intéressant.
Meilleurs vœux!
» répondre à ce commentaire
La construction d'arbres à l'aide de boucles a été implémentée
Publié par un invité le 25 mars 2004 à 22h10.
J'ai lu toutes les informations que vous avez fournies la dernière fois, mais pour être honnête, il n'y a pas beaucoup de nouveautés dans le premier article. Peut-être que je ne l'ai pas très bien compris. Le deuxième article a été écrit en PHP3, ainsi que la structure du programme. n'a pas été détaillé. Voir, trop d'intersections de fonctions sont utilisées.
Il se trouve que j'avais besoin d'utiliser des rôles d'utilisateur hiérarchiques dans un système, j'ai donc écrit le parcours basé sur l'idée d'un tableau, je n'ai pas eu le temps de le trier, alors je vais le mettre ici. à vous de jeter un œil. La base de données est ADODB et le programme est extrait directement du système. J'espère qu'il pourra être décrit clairement. Il utilise principalement les puissantes opérations de tableau de PHP et utilise des boucles pour effectuer la récursivité. Le commentaire est une méthode similaire, mais le timing de traitement des résultats est différent.
<?php
/**
* Afficher la liste
* @accès public
*/
fonction DispList()
{
//Mode d'affichage sans indentation
// $this->mIsDispListIndex = true;
// echo('<p align="right"><a href="?action=new&part=role">Ajouter un nouveau rôle</a> </p>'); ">Ajouter un nouveau rôle</a> </p>');"
//
// $this->mListTitle = 'Liste des rôles utilisateur';
// $this->SetDataOption('list');
//
// $this->SetQueryTable( array($this->mTableUserRole) );
//
// //Ordre de requête
// $this->SetQueryOrder( 'asc', $this->mTableUserRole, 'sequence' );
//
// $this->Query('list');
// parent::DispList();
// //Une autre méthode d'affichage, utilisant un tableau comme pile, A : enregistrez le rôle lors de la poussée sur la pile et supprimez la source après la poussée.
// $this->CheckProperty('mrDb');
// $this->CheckProperty('mrSql');
// $this->mrSql->Select('role, title, parent');
// $this->mrSql->From($this->mTableUserRole);
// $this->mrSql->Orderby('parent, séquence');
// $this->mRs = $this->mrDb->Execute($this->mrSql->Sql());
// si (0 < nombre($this->mRs))
// {
// $source = & $this->mRs->GetArray(); //Index numérique
// $pile = tableau(''); //pile
// $stacki = array(-1); //Correspond à la pile, enregistre le niveau des données dans la pile dans l'arborescence
// $cible = tableau();
// tandis que (0 < nombre($stack))
// {
// $item = array_shift($stack);
// $lev = array_shift($stacki);
// si (!vide($élément))
// {
// //Placez ici les données traitées dans le tableau cible
// array_push ($target, str_repeat(' ', $lev) . $item);
// //$s1 = str_repeat(' ', $lev) .
// }
// $del = array(); //Nœud à supprimer de $source
// $ar = array(); //Nœuds qui doivent être ajoutés à la pile
// foreach ($source comme $key=>$val)
// {
// //Trouver les nœuds enfants correspondants
// si (vide ($ article))
// {
// $find = vide ($source[$key]['parent']);
// }
//autre
// {
// $find = ($item == $source[$key]['parent']);
// }
// si ($trouver)
// {
// array_unshift($ar, $source[$key]['role']);
// $del[] = $clé;
// }
// }
// foreach ($ar comme $val)
// {
//array_unshift($stack, $val);
//array_unshift($stacki, $lev + 1);
// }
// foreach ($del comme $val)
// {
// non défini($source[$val]);
// }
// echo(implode(', ', $stack) . '<br />' . implode(', ', $stacki) . '<br />' . implode(', ', $target) . '< br /><br />');
// }
//debug_array();
// }
//autre
// {
// echo('<center>Aucune donnée récupérée</center>');
// }
//Une autre méthode d'affichage, utilisant un tableau comme pile, B : enregistrez l'index du tableau lorsque vous poussez la pile, sortez-le de la pile, puis supprimez la source après utilisation.
$this->CheckProperty('mrDb');
$this->CheckProperty('mrSql');
$this->mrSql->Select('role, title, parent');
$this->mrSql->From($this->mTableUserRole);
$this->mrSql->Orderby('parent, séquence');
$this->mRs = $this->mrDb->Execute($this->mrSql->Sql());
if (!empty($this->mRs) && !$this->mRs->EOF)
{
$source = & $this->mRs->GetArray(); //index numérique
$pile = tableau(-1); //pile
$stacki = array(-1); //Correspond à la pile, enregistre le niveau des données dans la pile dans l'arborescence
$cible = tableau();
tandis que (0 < nombre($stack))
{
$item = array_shift($stack);
$lev = array_shift($stacki);
si (-1 != $article)
{
//Mettez ici les données traitées dans le tableau cible
$s1 = str_repeat(' ', $lev) '<a href="?action=disp&part=role&role=' . $source[$item]['role'] . '">' $source[$item] ['titre'] '</a>';
$s2 = '<a href="?action=edit&part=role&role=' . $source[$item]['role'] . '">Modifier</a> <a href="?action=delete&part=role&role= ' . $source[$item]['role'] '">Supprimer</a>';
array_push ($ cible, tableau ($ s1, $ s2));
}
$del = array(); //Nœud à supprimer de $source
$ar = array(); //Nœuds qui doivent être ajoutés à la pile
foreach ($source comme $key=>$val)
{
//Trouver les nœuds enfants correspondants
si (-1 == $article)
{
$find = vide ($source[$key]['parent']);
}
autre
{
$find = ($source[$item]['role'] == $source[$key]['parent']);
}
si($trouver)
{
array_unshift($ar, $key);
}
}
foreach ($ar comme $val)
{
array_unshift($stack, $val);
array_unshift($stacki, $lev + 1);
}
//Supprimer de la source
unset($source[$item]);
//echo(implode(', ', $stack) . '<br />' . implode(', ', $stacki) . '<br />' . implode(', ', $target) . '< br /><br />');
}
//Sortir
echo('<p align="right"><a href="?action=new&part=role">Ajouter un nouveau rôle</a> </p>');
array_unshift($target, array('role', 'opération'));
$this->CheckProperty('mrLt');
$this->mrLt->SetData($target);
$this->mrLt->mListTitle = 'Liste des rôles utilisateur';
$this->mrLt->mIsDispIndex = false;
$this->mrLt->Disp();
}
autre
{
echo('<center>Aucune donnée récupérée</center>');
}
} // fin de la fonction DispList
?>