[php] Optimisation de ma classe 'Arbre de categories'

Optimisation de ma classe 'Arbre de categories' [php] - PHP - Programmation

Marsh Posté le 04-06-2008 à 22:18:38    

:hello:

 

Apres avoir appris l'objet cette année, j'ai decidé de reprendre mon site en objet :love:

 

J'utilise un singleton de connexion mysql, ma table categorie :

 

http://img521.imageshack.us/img521/8779/dbbo1.png

 

Le resultat à l'affichage :

 

http://img67.imageshack.us/img67/6875/screendm9.png

 

Je vous demande donc conseil pour essayer d'ameliorer ca, par ex, dans ma methode parents() je prefererais pas refaire une requete :/

 

Mon code :

 
Code :
  1. <?php
  2.     include_once("MysqlDB.php" );
  3.     
  4.     class CategorieTree {
  5.         private $id;
  6.         private $parent;
  7.         private $designation;
  8.         private $description;
  9.         private $enfants = array();
  10.         private $niveau;
  11.         private $visible = false;
  12.         
  13.         public function __construct($_id = 0, $_niveau = 0){
  14.             $this->id = (int)$_id;
  15.             $this->niveau = $_niveau;
  16.             if ($_id == 0){
  17.                 $this->parent = NULL;
  18.                 $this->designation = 'root';
  19.                 $this->description = NULL;
  20.             }
  21.             else{
  22.                 $query = MysqlDB::requete("SELECT * FROM categorie WHERE categorie.id = $_id" );
  23.                 $row = mysql_fetch_assoc($query);
  24.                 $this->parent = (int)$row['parent'];
  25.                 $this->designation = $row['designation'];
  26.                 $this->description = $row['description'];
  27.             }
  28.             $query = MysqlDB::requete("SELECT categorie.id FROM categorie WHERE categorie.parent = $_id" );
  29.             while ($row = mysql_fetch_assoc($query))
  30.                 $this->enfants[] = new CategorieTree($row['id'], $_niveau+1);
  31.         }
  32.         
  33.         public function affiche($_url, $_ulClass = "", $_tout = false){
  34.             if ($this->visible || $_tout){
  35.                 echo "<ul class=$_ulClass'" . $this->niveau . "'>\n";
  36.                 if ($this->id != 0)
  37.                     echo '<li><a href="' . $_url .  $this->id . '">' . $this->designation . "</a></li>\n";
  38.                 foreach ($this->enfants as $tree)
  39.                     $tree->affiche($_url, $_ulClass, $_tout);
  40.                 echo "</ul>\n";
  41.             }
  42.         }
  43.         public function ouvrir($_id = 0){
  44.             $this->ouvrir_enfants($this->parents($_id),1);
  45.         }
  46.         
  47.         public function ouvrir_enfants($_parents, $_cpt){
  48.             $this->visible = true;
  49.             foreach ($this->enfants as $cat){
  50.                 $cat->visible = true;
  51.                 if ($_cpt < sizeof($_parents) && $cat->id == $_parents[$_cpt])
  52.                     $cat->ouvrir_enfants($_parents, $_cpt+1);
  53.             }
  54.         }
  55.         
  56.         private function parents($_id){
  57.             $parents = array();
  58.             $parents[] = $_id;
  59.             while (end($parents) != 0){
  60.                 $query = MysqlDB::requete("SELECT parent FROM categorie WHERE id=" . end($parents) . "" );
  61.                 $row = mysql_fetch_assoc($query);
  62.                 $parents[] = (int)$row['parent'];
  63.             }
  64.             return array_reverse($parents);
  65.         }
  66.     }
  67. ?>
 

ya des optis a faire ?

Message cité 1 fois
Message édité par tomsoft le 09-06-2008 à 13:17:29
Reply

Marsh Posté le 04-06-2008 à 22:18:38   

Reply

Marsh Posté le 04-06-2008 à 22:21:29    

a faire : verifier que la cat soit bien dans la bdd :lol:
 
utilisation :  
 

Code :
  1. <?php
  2.     include_once("../classes/CategorieTree.php" );
  3.  
  4.     $tree = new CategorieTree;
  5.     $tree->ouvrir($_GET['cat']);
  6.     $tree->affiche("?cat=" );
  7. ?>


 
en pensant a verifier que $_GET['cat'] est set :jap:

Reply

Marsh Posté le 04-06-2008 à 23:46:57    

tomsoft a écrit :

:hello:

 

Apres avoir appris l'objet cette année, j'ai decidé de reprendre mon site en objet :love:

 

J'utilise un singleton de connexion mysql, ma table categorie :

 

http://img521.imageshack.us/img521/8779/dbbo1.png

 

Le resultat à l'affichage :

 

http://img67.imageshack.us/img67/6875/screendm9.png

 

Je vous demande donc conseil pour essayer d'ameliorer ca, par ex, dans ma methode parents() je prefererais pas refaire une requete :/

 

Mon code :...

 

ya des optis a faire ?

 

Je pense pas que ce soit tellement optimisable ...
En tout cas, c'est propre, c'est rare de voir du beau PHP comme ça, avec séparation des données et de leur traitement ...

 

Juste pour info, si tu veux faire du pur objet, ruby on Rails te permet de réécrire tout ce code en :

Code :
  1. class CategorieTree < ActiveRecord::Base
  2.  act_as_tree :order=>:designation
  3.  
  4.  def to_s
  5.    children.each{
  6.      ret=""
  7.      ret += "<li>#{description}</li>" if this.parent
  8.      children.each { |c| ret+="<ul>#{c}</ul>" if this.children.length > 0 }
  9.  end
  10. end


Tu as alors les méthodes (entre autres) :

Code :
  1. CategorieTree.find(:all)
  2. c=CategorieTree.find_by_parent_id(1)
  3. d=CategorieTree.new()
  4. d.description="azerty"
  5. d.save
  6. cats=c.children
  7. root=c.parent
  8. root=c.root()
  9. parents=c.ancestors()
  10. d.create(:designation=>"azer", :parent=>c, :description=>"blabla" )
  11. c.update(:description=>"blablabla" )


et si tu fais l'équivalent d'un 'echo $c' en PHP
tu as directement tout qui s'affiche ...

 

Bref, tout le code est allégé ...

 



Message édité par Paulp le 04-06-2008 à 23:47:35
Reply

Marsh Posté le 04-06-2008 à 23:57:28    

hum simpa ce ruby on rails :)
 
merci, mais une idée pour ma fonction parents qui integroge n fois ma bdd ?

Reply

Marsh Posté le 05-06-2008 à 00:37:53    

Les associations réflexives sont très consommatrices en requêtes, la vraie bonne solution pour éviter d'avoir trop de requêtes c'est les procédures stockées mais bon niveau compatibilité c'est pas top. Sinon il y a des variantes suivant ce qu'on est prêt à sacrifier ou que l'on tient absolument à respecter. La conception ultime n'existe pas, il a toujours des avantages et des inconvénients.
 
Essaie juste d'éviter d'avoir la ("fonction parents qui integroge n fois ma bdd" x i x j) ^ ("fonction parents qui integroge n fois ma bdd" x k x l).


Message édité par czh le 05-06-2008 à 00:39:25
Reply

Marsh Posté le 05-06-2008 à 00:42:53    

tomsoft a écrit :

hum simpa ce ruby on rails :)
 
merci, mais une idée pour ma fonction parents qui integroge n fois ma bdd ?


 
A la limite, la représentation intervallaire :
http://www.siteduzero.com/tuto-3-2 [...] laire.html
http://sqlpro.developpez.com/cours/arborescence/#L2
 
tu as ton noeud courant $n
Tu veux ses ancetres :
SELECT * FROM categorie WHERE borne_gauche < {$n->borne_gauche} and borne_droite > {$n->borne_droite} ORDER BY borne_gauche
pour les enfants directs :
SELECT * FROM categorie WHERE borne_gauche > {$n->borne_gauche} and borne_droite < {$n->borne_droite} and niveau={$n->niveau}+1 ORDER BY borne_gauche
pour les descendants :
SELECT * FROM categorie WHERE borne_gauche > {$n->borne_gauche} and borne_droite < {$n->borne_droite} ORDER BY borne_gauche
 
C'est assez puissant ...
Et pour l'affichage
SELECT * FROM caregorie ORDER BY borne_gauche
Et tu as toutes tes catégories dans l'ordre :

Code :
  1. $prev=0;
  2. echo "<ul>";
  3. while($cat = mysql_fetch_object($result)){
  4.  if($cat->niveau > $prev)
  5.    echo "<ul>";
  6.  if($cat->niveau < $prev)
  7.    echo "</ul>";
  8.  echo "<li>".$cat->description."</li>";
  9. }
  10. echo "</ul>";


Message édité par Paulp le 05-06-2008 à 00:53:54
Reply

Marsh Posté le 08-06-2008 à 22:23:53    

:jap:
 
Je vais laisser comme cela pour le moment ;) c'est assez rapide pour ce que j'ai a faire ;)
 
sino je l'ai enrichit d'une nouvelle methode (2 exactment) pour selectionner une cat dans un select option :
 

Code :
  1. public function affiche_select($_selectName = 'categorie'){
  2.     echo "<select name='$_selectName'>";
  3.     $this->affiche_select_r();
  4.     echo "</select>\n";
  5. }
  6.  
  7. public function affiche_select_r(){
  8.     if ($this->id != 0){
  9.         echo '<option name="' . $this->id . '">';
  10.         for ($i = 1; $i < $this->niveau; $i++)
  11.             echo '&nbsp;&nbsp;&nbsp;&nbsp;';
  12.         echo $this->designation . "</option>\n";
  13.     }
  14.     foreach ($this->enfants as $tree)
  15.         $tree->affiche_select_r();
  16. }


 
une methode d'init qui appele une methode recursive :)
 
au fait, ya un moyen d'inserer une tab en html ? pour eviter le "&nbsp;&nbsp;&nbsp;&nbsp;" :d


Message édité par tomsoft le 08-06-2008 à 22:24:28
Reply

Marsh Posté le 09-06-2008 à 11:19:53    

Utilise plutôt les styles css, tu gagneras en souplesse pour modifier l'apparence

Reply

Marsh Posté le 09-06-2008 à 11:20:57    

je peut appliquer un style css dans un "<option>" ? :heink:

Reply

Marsh Posté le 09-06-2008 à 13:43:15    

Code :
  1. <select name="hihi">
  2.   <option style="text-indent:5px;">Un</option>
  3.   <option style="text-indent:10px;">Deux</option>
  4.   <option style="text-indent:15px;">Trois</option>
  5. </select>


ça marche sous FF au moins :o
(IE 7 n'en a cure par contre)


Message édité par PunkRod le 09-06-2008 à 13:44:11
Reply

Marsh Posté le 09-06-2008 à 13:43:15   

Reply

Marsh Posté le 09-06-2008 à 13:59:57    

oui pareil avec un margin-left, mais IE s'en tappe royal :lol:

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed