IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

[Conception] class au dessus d'une base de donnée


Sujet :

PHP & Base de données

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juin 2006
    Messages : 6
    Points : 5
    Points
    5
    Par défaut [Conception] class au dessus d'une base de donnée
    Bonjour,
    J'ai créé un site avec consultation d'une base de données. Je decouvre actuellement php et mysql aussi mon travail n'est il pas pertinent. J'ai décidé de revoir mon travail et c'est durant cette revision que l'envie d'utiliser des classes m'est venue.
    Je tiens, a ce niveau, a preciser que mon site n'a aucune finalité si ce n'est me faire decouvrir php.
    Mon probleme, quant a lui concerne la conception même des classes que je souhaiterai utiliser : mon manque d'experience ou mes difficultés a cerner mon probleme font que je ne trouve pas de doc donnant une methode complete de la marche que j'aimerai suivre. Même si certaines m'ont donné des pistes de reflexions interessantes je me trouve actuellement a critiquer l'utilité de telles classes (car je ne comprends pas tout ^^)

    Mon post est assez long j'en suis desolé, je vais presenter une page que je possede. l'utilisation d'une classe pour cette page et m'arreterai la pour ne pas devenir trop illisible :

    une de mes pages consulte une table de ma base et affiche et mets en page tous ses champs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <?php
    ob_start("ob_gzhandler");
    require("connection.php");
    require("head.html");
    ?>
     
    <div id="contenu">
     
    <h2>Nos partenaires</h2>
     
    <p>Un merci a tous ceux qui contribuent a la santé de notre club.</p>
     
    <?php 
     
    require("script/fonction.php");//fonction contient la class abstraite utilitaire
     
    //affiche les partenaires
     
    $REQUET="select * from partenaire";
     
    if($RESULT=mysql_query($REQUET)){
     
      while($LIGNE=mysql_fetch_object($RESULT)){
     
        $NOM=$LIGNE->par_nom;
        $DESCR=$LIGNE->par_descr;		
        $IMG=$LIGNE->par_img_id;
        $URL=$LIGNE->par_url;
     
        if(!empty($IMG)){
          $IMG=utilitaire::chemin_Img($IMG);//chemin_Img crée le chemin de l'image voulue
          $IMGECHO="<img src=\"$IMG\" alt=\"logo de $NOM\" >";				
        }
        else{
          $IMGECHO= "photo pas encore en ligne";
        }
        $AFFICHAGE="<h3>$NOM</h3>";
        $AFFICHAGE.= "<div class=\"partenaire\">$IMGECHO  <i>$DESCR</i>";
        if(!empty($URL)){
          $AFFICHAGE.=" <br/>lien direct : <i><a href=\"$URL\">$NOM</a></i>";
        }
        $AFFICHAGE.= "</div>";
        echo $AFFICHAGE;
      }
    }
    else{
      echo"echec requete";
    }
    require("footer.html");
    ?>
    ps: il est fort probable que sous cette forme mon travail ne soit pas structuré ou pro n'hesitez pas a critiquer les faiblesses de mon travail

    Admettons que je souhaite créer une classe partenaire, quelles sont les questions a se poser?
    dois je créer une classe correspondant a tous les champs de la table que je stockerai ds un tableau parcouru par les methodes de la base? (ça me parait moche et je pense mal formuler l'idée.)
    A l'heure actuelle je pense a quelque chose ressemblant a ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class partenaire{
         private $OBJET
        //je ne crée pas de constructeur
     
        function get_id($ID){//on sort les infos d'un seul partenaire
                  $REQUET="select * from partenaire where $ID=part_id";
                  $RESULT=mysql_query($REQUET);
                  $OBJET=mysql_fetch_object($RESULT);
        }
     
         function nom(){
                  return $OBJET->part_nom;
          }
     
         //etc pour le reste
    }
    La premiere version sort tout seul tous les partenaires qu'il met en page (une seule requete). La je ne sors qu'un seul partenaire a la fois. Ce qui pose plusieurs problemes selon moi :
    Comment savoir que tous mes partenaires ont été bien affiché ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $PARTENAIRE=1;//pour entrer dans la boucle
    $I=1;
    while($PARTENAIRE){
      $PARTENAIRE=new partenaire;
      $PARTENAIRE->get_id($I);//soit 20 partenaires alors j'ai 20 requetes :'(
       affichage($PARTENAIRE);//s'occupe de la mise en page peut mm etre 
    //une methode de la classe donc plutot $PARTENAIRE->affichage()
    $I+=1;
    }
    Voici en l'etat actuel de mes connaissances l'equivalent avec classe de mon probleme. Evidement l'avantage est que je peux maintenant utiliser cette classe sur d'autres pages ou je n'ai besoin que d'un partenaire particulier , l'inconvenient ici est le nombres élevé de consultation de la base.

    Je m'arrete la en remerciant ceux qui ont lu jusqu'au bout (en esperant etre interessant) N'hesitez pas a critiquer ou commenter ce que je viens d'ecrire cela m'aiderai beaucoup.
    Merci d'avance.

  2. #2
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 021
    Points : 2 278
    Points
    2 278
    Par défaut
    Salut,
    si tu veux vraiment programmer objet je pense qu'il faut que tu partes encore de plus générique.
    Perso j'ai développé des classes dont je me sers partout :

    SqlRecord (enregistrement SQL)
    SqlRecordsSet (ensemble d'enregistrements SQL)

    L'intérêt et qu'ensuite tu les étends et tu te retrouves à juste modifier des affichages ou des formulaires, toutes les opérations SQL existent déjà dans les classes mères (enfin dans l'idéal ^^).

    Voici leurs structures simplifiées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class SqlRecord() {
    	var $table; 	// Nom de la table dans la BDD
    	var $key; 	// Clé
    	var $fields;    // Tableau des champs de l'enregistrement
     
    	function SqlRecord($table = null, $key = null)	{}
    	function sqlSelect($where = NULL)	{}
    	function sqlInsert()	{}
    	function sqlDelete()	{}
    	function sqlUpdate()	{}
    	function getField($name)	{
    		if(isset($this->fields[$name]))
    			return $this->fields[$name];
    		return NULL;
    	}
    }
     
    class SqlRecordsSet {
     
    	var $table = null; 	// Nom de la table dans la BDD
    	var $records = null;  	// Tableau des objets SqlRecord
    	var $fields;    // Tableau des champs des enregistrements à traiter
     
    	function SqlRecordsSet($table = NULL, $ids = NULL)	{}
    	function sqlInsert()	{}
    	function sqlDelete()	{}
    	function sqlUpdate()	{}
    	function sqlSelect()	{// c'est là que tu fais ton unique requête pour tous tes enregistrements plutôt que d'en faire 20}
    }
    Ensuite tu as plus qu'à étendre.
    class Partenaire extends SqlRecord
    class PartenairesEnsemble extends SqlRecordsSet
    class Client extends SqlRecord
    etc.

    En plus de la réutilisabilité du code cela facilite également la maintenance. Mettons que t'aies oublié de traiter les injections sql, tu as juste à modifier ta fonction sqlSelect() et c'est bon.
    Vive les roues en pierre

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juin 2006
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Merci pour ta reponse mais je m'interroge encore :

    chaque classe enfant heritera donc du tableau $field et aura la methode getfield et affichage (voir plus bas, c'est une methode que j'ai ajouté) c'est bien ça ?
    De plus cela ne pose t'il pas probleme le fait qu'elles soient autant generaliste? Elles semblent permettre les insertions, modification...

    Partons du principe que les insertions ne sont permises que dans un module admin ne vaudrait il pas mieux créer une autre classe gerant ces details de maintenance?
    Idealement je permettrai a ces classes de consulter ma base (select) et eventuellement de formater un certain affichage (avec la methode affichage dont je parlais) et celles du module admin a faire le reste.

    Je me permets de reprendre et adapter mon exemple sur SqlRecord :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    class SqlRecord() {
    	var $table; 	// Nom de la table dans la BDD
    	var $key; 	// Clé
    	var $fields;    // Tableau des champs de l'enregistrement
     
    	function SqlRecord($table = null, $key = null)	{}
    	function sqlSelect($where = NULL)	{}
    	function getField($name)	{
    		if(isset($this->fields[$name]))
    			return $this->fields[$name];
    		return NULL;
    	}
            function affichage(){
                 //ici on permet la mise en page des données sorties par la classe
                 //je ne l'ecris pas, ce n'est pas le but de mon post :P
            }
    }
    A ce stade je me pose une question sur la difference entre le constructeur SqlRecord et la methode SqlSelect :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function SqlRecord($table = null, $key = null)	{}
    Va me permettre de sortir un champ de ma base si la cle existe. (Si la cle n'existe pas il va falloir le signaler ou l'objet gere seul?)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function sqlSelect($where = NULL)	{}
    C'est une methode de l'objet. Mais que consulte t'elle? elle refait une connexion a la base en utilisant le contenu de $table et $key et en ajoutant un where?
    Donc par exemple je peux instancier un objet correspondant au partenaire 1. Et avec cette methode verifier (en resortant le champ de la base) si son nom est COFADAS par exemple (where nom_part=COFADAS). Si c'est bien cela, alors je ne comprends pas trop l'interet. Je possede getField et je peux l'utiliser pour prendre les clefs de $field comme critere.

    la methode SqlSelect n'est elle pas plus pertinente dans la classe SqlRecordSet et inutile ici?

    Mon post va devenir indigeste si je continue. Je posterai plus tard ce que j'ai compris de ta solution adapté a mon exemple.

  4. #4
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 021
    Points : 2 278
    Points
    2 278
    Par défaut
    Au niveau du découpage, tu peux effectivement faire plus propre en créant une classe d'enregistrement en lecture seule et une en lecture/écriture qui l'étend (tu auras un petit gain de mémoire de quelques octets pour les pointeurs de fonctions, par contre niveau de la sécurité ca changera rien) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SqlRRecord() {
      sqlSelect()
      sqlGetField()
    }
     
    SqlRWRecord extends SqlRRecord() {
      sqlInsert()
      sqlUpdate()
      sqlDelete()
    }
    Au sujet de la fonction affichage() le but c'est justement de la mettre dans Partenaire et non dans SqlRecord ou bien dans mettre très générique dans SqlRecord du style affichage() {echo implode(',', $this->fields)}.

    Le constructueur ne fait aucune opération SQL, il sert juste à définir la table et/ou la clé. C'est sqlSelect() qui s'occupe de remplir le tableau $fields. En fait sqlSelect() sert à "charger" les champs de l'objet en mémoire en faisant la requête "SELECT". getField() sert juste à récupérer un champ dans le tableau, il n'effectue aucune requête.

    Donc par exemple je peux instancier un objet correspondant au partenaire 1. Et avec cette methode verifier (en resortant le champ de la base) si son nom est COFADAS par exemple (where nom_part=COFADAS).
    En effet mais si tu n'as pas la clé, ca te permet de récupérer un enregistrement en fonction d'une condition différente de "clé = truc".

    Comme je te le disais c'est juste un exemple, j'ai pas le code de la dernière version que j'ai faite sous les yeux mais ensuite cela devient un peu plus ardus de gérer les jointures, etc.
    Vive les roues en pierre

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juin 2006
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Voici donc (avec plein de commentaire) ce que j'ai compris :
    Comme dit plus haut le php est nouveau pour moi donc tous mes posts ne sont pas la pour critiquer la methode de djakisback juste que je suis un joyeux neophyte.

    Je reprends ce que j'ai dit avoir compris plus haut moins mon histoire d'affichage (qu'une telle methode existe ou non n'a pas d'insidence sur la classe selon moi). Ma vision va faire subir des modifications aux exemples precedents mais c'est parce que je ne comprends pas leur fonctionnement exact.

    Soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    class SqlRecord {
    	var $table; 	// Nom de la table dans la BDD
    	var $key; 	// Clé
    	var $fields;    // Tableau des champs de l'enregistrement
     
    /* le constructeurs est necessaire pour les classes heritiaires
    et la fonction sqlSelect pretend a etre virtuelle?*/
    	function SqlRecord($table = null, $key = null)	{}
    	function sqlSelect($where = NULL)	{}
    	function getField($name)	{
    		if(isset($this->fields[$name]))
    			return $this->fields[$name];
    		return NULL;
    	}
    }
    Je reprends donc l'idée de partenaire pour obtenir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    class Partenaire extends SqlRecord{
     
           //on herite des variables de SqlRecord 
           //j'ajoute une variable verifiant si la requete a fonctionnée
           //cette variable devrait etre ajoutée ds la classe ancetre
           var $ok;
     
           function Partenaire($key=1){//valeur par defaut
               //je ne passe pas $table en parametre car $table est ici partenaire
               $table="partenaire";
               $requet="select * from $table where part_id=$key";
               $result=mysql_query($requet);
                if($ligne=mysql_fetch_object($result)){
                       $field[id]=$ligne->part_id;
                       $field[nom]=$ligne->part_nom;
                       //...
                       ok=true;
                 }else {ok=false; }
            }
     
            //comme dit plus haut SqlSelect m'est hermetique :( 
            // et inutile de reprendre getfield (vive l'heritage)
     }
    Au final je n'ai pas compris grand chose apres une journée de reflexion tout de même. Mais ces utilisations de classes avec heritages sont nettement plus agreables que mon jet lors de ma premiere question.
    Si certaines choses sont ameliorable ou s'il manque certains principes ou idées dans mon approche n'hesitez pas a repondre ou a m'envoyer un mp.
    Merci d'avance

    edit: je viens de voir ta reponse apres mon post, j'ai ecrit cela pour rien :'(

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 05/10/2006, 17h15
  2. [Conception] mise à jour automatique d'une base de donné distante
    Par bipbip2006 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 01/06/2006, 16h45
  3. [Conception] Code php dans une base de donnée
    Par krfa1 dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 13/09/2005, 10h58
  4. [Conception] Gestion des accents dans une base de données
    Par MiJack dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 07/07/2005, 11h41
  5. [Concept] Stabilité d'une base de donnée
    Par lassmust dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 03/07/2002, 16h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo