Gestion de site via des arbres (représentation intervallaire...)
Hors ligneDolfinger Le 04/05/2006 à 12:18 Profil de Dolfinger Configuration de Dolfinger

Salut à tous,
Je me demandais si l'un d'entre vous avait déjà essayer ce genre de systeme entre autre pour la gestion d'un site et de son arborescence. Si oui ou non qu'en pensez vous ? J'ai fait quelques tests et il se trouve que c'est très fonctionnel, notamment pour la gestion de sous-sous section l'ajout etc.

Voici comment j'ai envisagé les choses,
une table principale 'arbo' contient les champs id,gauche,droite,niveau,nom,description et pageid ; une seconde table 'pages' contient quand à elle le contenu pointé par arbo.pageid.
Pour chaque noeud ou feuille de la table 'arbo' on associe une borne droite et gauche ainsi qu'un niveau correspondant à sa hauteur dans l'arbre. Le principe de représentation est simple, on part de la racine avec une valeur initiale de 1 et l'on suis "toujours à gauche". A chaque noeud ou feuille croisé on ajoute 1 et la valeur est attribuée à 'gauche'. Une fois arrivé sur une feuille on remonte à droite pour redescendre à gauche etc. jusqu'à remonter finalement à la racine.
=> Chaque feuille aura droite = gauche +1 et chaque noeud aura une difference plus importante qui vaudra 2fois le nombre d'élément sous ce noeud.

Voila en gros le principe (assez mal expliqué je le reconnais, mais vous pouvez consulter sur ce site le principe de fonctionnement en détail).

Je suis partis de ce système et j'y ai rajouter un champ de description ainsi qu'un champ de page.
Ainsi la génération du menu ou d'un plan de site est tres simple et ne nécessite qu'une seule requète, idem pour la page actuelle. L'avantage etant que l'on peut automatiser toute la gestion d'articles par exemple dans une catégorie définie mais tout en gardant une en-tete descriptive.
L'inconvéniant majeur pour l'instant qui me pose problème est qu'il est difficile de faire des pages "hors normes" (avec du code php spécifique).

Voila dites moi ce que vous en pensez (surtout si vous avez des idées pour l'améliorer :p) pour l'instant la gestion de toute les rubriques du site tiens sur 50 lignes (3 fonctions) (Affichage uniquement pas administration).

A++ :)
Hors ligneAnthony Le 05/05/2006 à 11:50 Profil de Anthony Configuration de Anthony

Admin
Salut,

c'est une question assez longue à traiter, je vais regarder ce soir ou ce week end, tu auras une réponse de ma part d'ici là ;)
--

Hors ligneAnthony Le 07/05/2006 à 23:35 Profil de Anthony Configuration de Anthony

Admin
En fait j'aimerais voir ton code et ce que tu voudrais améliorer, car je suis en train de lire le pavé sur developpez.com (qui ma foi est très intéressant), mais j'aimerais voir la structure de ta table et ton code afin de voir si tes requêtes sont optimisées (et ton code php au passage).

Sinon si tu es satisfait de cette solution et qu'elle mange une seule requête, tu peux je pense la garder
--

Hors ligneDolfinger Le 25/05/2006 à 15:08 Profil de Dolfinger Configuration de Dolfinger

Salut :)
Désolé de répondre aussi tardivement, n'etant plus chez moi je n'avait pas accès au code source (pas pensé à l'embarquer...).
Bref voici le code que j'utilise, il y a certainement pas mal d'améliorations à faire...

Il s'agit là du fichier functions.php, la page principale ne fesant que des appels à ces fonctions :





<?php
/**
* Culture Science
*
* functions.php
* Fonctions principales du site
*
* @author  -------- ----
* @version 1.0 (02-05-2006)
*
*/


/**
* Dépendance(s)
*/
require_once('./conf.php');

/**
* dateFr
* Convertis une date US au format FR
* @param $d : date au format US
* @return   : date au format "jj/mm/aaaa à hh:mm"
*/
function dateFR($d){
  $date = substr($d,8,2)."/";               // jour
  $date = $date.substr($d,5,2)."/";          // mois
  $date = $date.substr($d,0,4). " à ";     // année
  $date = $date.substr($d,11,5);          // heures et minutes
  return $date;
}

/**
* Arbo
* Permet d'afficher une arborescence
* @param $p : racine de l'arborescence
* @param $m : profondeur max à partir de $p dans l'arborescence
*                  si $m vaut -1 il n'y a pas de limites
* @param $styles : tableau de classes de styles
*/
function Arbo($p ,$m, $styles){
     // Connection     
     $link = my_connect();
     
     
// Création de la requète en fonction de $m
     if($m<0){
          $query = "SELECT * FROM site
                      WHERE niveau>=$p
                      ORDER BY gauche"
;
     } else {
          $query = "SELECT * FROM site
                      WHERE niveau>=$p AND niveau<=$p+$m
                      ORDER BY gauche"
;
     }
     $req = mysql_query($query,$link) or die(mysql_error());
     
     
// On utilise une variable pour connaitre le niveau du prédécésseur
     $prec = $p;
     $i = 0;
     echo "\n\t\t<ul>";
     
     
// On parcours toute l'arborescence
     while($i<mysql_num_rows($req)){
          $ligne = mysql_fetch_assoc($req);
          $niv = $ligne['niveau'];
          $nom = $ligne['nom'];
          $page = $ligne['page'];     
          if
(count($styles)>$niv-$p) {
               $css = " class =\"".$styles[$niv-$p]."\"";
          }
          else {
               $css = '';
          }
          
          
// On remonte d'un niveau
          if($niv < $prec) {
               echo "\n\t\t</ul>";
          }
          // On descend d'un niveau
          if($niv > $prec) {
               echo "\n\t\t<ul>";               
          
}     
               
          
// Dans tous les cas on affiche l'élément courant
          echo "\n\t\t<li",$css,">";
          echo "<a href=\"./?p=",$page,'">',$nom,"</a></li>";
          
          
// Incrémentation
          $prec = $niv;
          $i++;
     }
     
     
// On remonte jusqu'à la racine de l'arbre pour refermer les balises
     while($niv >= $p){
          echo "\n\t\t</ul>";
          $niv--;
     }
     
     
     
// Déconnection
     mysql_close($link) or die(mysql_error());;
}


/**
* Page
* Vérifie si le parametre de page est correct
* Si oui on affiche la page correspondante
*/
function Page(){
     // On vérifie si une page est passée en parametre
     if(isset($_GET['p']) && $_GET['p']>=0) {
          $page = $_GET['p'];
     } else {
          $page = 0;
     }
     
     
// Connection
     $link = my_connect();
     $query = "SELECT * FROM pages,site
                 WHERE pages.id=$page AND site.page=$page"
;
     $req = mysql_query($query,$link) or die(mysql_error());

     // On vérifie que 1 seule page correspond à l'id fournis,
     // sinon on utilise par défaut la page ayant l'id 0
     if(mysql_num_rows($req)!=1){      
          $query
= "SELECT * FROM pages,site
                      WHERE pages.id=0 AND site.page=0"
;
          $req = mysql_query($query,$link) or die(mysql_error());
     }
     
     
// On affiche le titre et le contenu de la page
     $arr = mysql_fetch_assoc($req);
     echo '<h1>',$arr['nom'],'</h1>',$arr['contenu'];
     $g = $arr['gauche'];
     $d = $arr['droite'];
     $n = $arr['niveau'];
     
     
// Si cette page est une feuille on affiche en plus directement
     // l'auteur et la date
     if($d-$g==1){
          echo '<h5>Par ',$arr['auteur'],' le ',dateFr($arr['dateHeure']),'</h5>';
     }
     
     
// Sinon (la page est un noeud), on vérifie si le listning des sous
     // catégories est autorisé. Si c'est le cas on les affiche
     elseif($arr['listing']==1) {
          $query = "SELECT * FROM site,pages
                      WHERE gauche>$g AND droite<$d AND site.page = pages.id AND niveau = $n+1"
;
          $req = mysql_query($query,$link) or die(mysql_error());
          $arr=mysql_fetch_assoc($req);
          
          
// Affichage
          do {
               echo '<h4><a href=\'./?p=',$arr['page'],'\'>',$arr['nom'],'</a></h4>';
               echo '<div class=\'divQuote\'>',$arr['description'],'</div>';
          } while($arr=mysql_fetch_assoc($req));
     }
     
     
// Déconnection
     mysql_close($link) or die(mysql_error());
}

?>


Pour afficher une arborescence on utilise par exemple :


<?php
Arbo
(1,1,array('cat','sousCat'));
?>


Ici on affiche l'arborescence à partir du niveau 1 (celui juste apres la racine de l'arbre) et jusqu'au niveau 2 (1+1).
On applique les styles css 'cat' aux niveaux 1 et 'sousCat' aux niveaux 2

Le rendu sera par exemple :


          <ul>

          <li class ="cat">
<a href="./?p=1">Site</a></li>

          <ul>
          <li class ="sousCat">
<a href="./?p=3">News</a></li>
          <li class ="sousCat"><a href="./?p=4">Archives</a></li>
          <li class ="sousCat"><a href="./?p=5">Forum</a></li>
          </ul>
          <li class ="cat">
<a href="./?p=2">Articles</a></li>
          <ul>
          <li class ="sousCat">
<a href="./?p=7">Chimie</a></li>
          <li class ="sousCat"><a href="./?p=8">Biologie</a></li>
          <li class ="sousCat"><a href="./?p=9">Electronique</a></li>
          </ul>

          </ul>



Ce qui me pose problème en ce moment :

  • Le html dans le code php, notemment dans la génération d'arborescence... Pour cela je ne vois pas tellement d'autres alternatives, peut etre avec les templates mais ca deviendrait vraiment lourd pour pas grand chose
  • L'indentation du code html généré qui est pas clean, je vais peut etre utiliser tidy, à voir



Sinon les temps de générations moyens sont de l'ordre de 4ms pour une arborescence et 10ms pour une page complète (à noter que sous firefox c'est bien plus long...) mais bon ces résultats sont certainements à revoir à la hausse puisque j'ai tester en local.

Voila, dites moi ce que vous en pensez ;)

++


Dolf

Hors ligneAnthony Le 25/05/2006 à 15:47 Profil de Anthony Configuration de Anthony

Admin
Tu peux supprimer le ",$link" dans les mysql_query, ça ne sert à rien ;)

Sinon évites les requêtes en SELECT *, mets les champs dont tu as besoin dans la requête.

Le mysql_close() tu peux le placer après le mysql_query, ça t'évitera de te chopper des erreurs de max_user_connections ;)

  $date = substr($d,8,2)."/";               // jour
  $date = $date.substr($d,5,2)."/";          // mois
  $date = $date.substr($d,0,4). " à ";     // année
  $date = $date.substr($d,11,5);          // heures et minutes

tu peux remplacer les $date = $date.

ça donne ça :

  $date  = substr($d,8,2).'/';               // jour
  $date .= substr($d,5,2).'/';          // mois
  $date .= substr($d,0,4).' à ';     // année
  $date .= substr($d,11,5);          // heures et minutes

Supprime ensuite ta variable $i pour l'incrémentation :

     while($i<mysql_num_rows($req)){
          $ligne = mysql_fetch_assoc($req);

vaut mieux le remplacer par ça :

while($ligne = mysql_fetch_assoc($req))
{

etc...


Pour la vérification des pages :

if(isset($_GET['p']) && $_GET['p']>=0) {

attention aux failles de SQL injection,  vérifies que ta page entrée est numérique au moins :

if(isset($_GET['p']) && is_numeric($_GET['p']) && $_GET['p']>=0){
--

Hors ligneDolfinger Le 25/05/2006 à 17:47 Profil de Dolfinger Configuration de Dolfinger

Justement pour l'injection j'avais essayer is_integer() et à priori il fonctionnait pas, puisqu'il s'agit d'une chaine numéric j'avais pas pensé à is_numeric()...
En testant si c'est superieur à 0 normalement ca vérifie également le type non?
Enfin quand je met du texte par exemple à la place du chiffre le if reste faux.
Pour le $i c'est un vieux reste de code que j'ai pas pensé à changer où j'avais besoin de connaitre l'iteration en cours

En tout cas merci pour les détails je m'etais pas encore attelé à l'opti meme si ca devrait etre automatique
Hors ligneAnthony Le 25/05/2006 à 17:52 Profil de Anthony Configuration de Anthony

Admin
Le is_int ne fonctionnera pas car la chaîne passée en paramètre est une string, il faut donc utiliser ctype_digit() si tu veux savoir si c'est un entier ou alors is_numeric() (entier ou flottant). Ayant eu des problèmes avec ctype_digit je ne l'utilise pas. et le >=0 ne dispense pas du is_numeric() :)
--

Hors ligneDolfinger Le 25/05/2006 à 17:53 Profil de Dolfinger Configuration de Dolfinger

Ok merci pour la précision
Vous avez résolu votre problème avec VIC ? Faites-le savoir sur les réseaux sociaux !
Vulgarisation-informatique.com
Cours en informatique & tutoriels