begin process at 2008 08 20 12:26:00
1 228 823 membres
193 nouveaux aujourd'hui
14 257 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

CLASSE PHP4 DE CONNEXION À UN SGBD


Information sur la source

Description

Cette classe relativement simple n'est pas non plus très original étant donné qu'il en existe de nombreuses sur le sujet.
Elle permet la connexion et l'exécution de requête sur n'importe quel SGBD en réécrivant la classe fille adaptée et en ajoutant une instruction à la fonction connexion().
Je n'est pour l'instant qu'écrit une sous classe pour MySQL.
Elle est écris pour PHP4.
Les erreurs peuvent soit être traitées avec une gestion personnalisée, soit au cas par cas.

J'aimerais savoir ce que vous en pensez

Source

  • <?php
  • // Classe abstraite définissant une interface générique d'accès à une base de données
  • class BASE
  • {
  • // propriétés protégée
  • var $connexion;
  • var $messExplicatif;
  • var $codeErreur;
  • var $messErreur;
  • var $SGBD;
  • // Constructeur de la classe
  • function BASE($login, $motDePasse, $base, $serveur)
  • {
  • // Initialisations
  • $this -> messExplicatif = "";
  • $this -> codeErreur = 0;
  • $this -> messErreur = "";
  • $this -> sgbd = "Indefini";
  • // Connexion au serveur par appel à une méthode privée
  • if (!$this -> connexion = $this->connect($login, $motDePasse, $base, $serveur))
  • {
  • $this -> messExplicatif = "Erreur de connexion au SGBD " . $this->sgbd . ": <BR> " . $this->messageSGBD();
  • }
  • }
  • // Fin du constructeur
  • // Méthodes privées
  • // Méthodes abstraites
  • function connect($login, $motDePasse, $base, $serveur) {}
  • function exe ($requete) {}
  • // Méthode de mise en forme du message d'erreur du SGBD
  • function messageSGBD ()
  • {
  • return "Libelle erreur : ".$this->messErreur."<BR />Num erreur :".$this->codeErreur;
  • }
  • // Méthodes publiques
  • // Méthode d'exécution d'une requête
  • function exeRequete ($requete)
  • {
  • if (!$resultat = $this -> exe ($requete))
  • {
  • $this -> messExplicatif = "Problème dans l'exécution de la requête : " . $requete . "<BR> " . $this->messageSGBD();
  • }
  • else
  • {
  • return $resultat;
  • }
  • }
  • // Retour du message d'erreur
  • function messageExplicatif ()
  • {
  • return $this->messExplicatif;
  • }
  • // Méthodes abstraites
  • // Accès à la ligne suivante, sous forme d'objet
  • function objetSuivant ($resultat) {}
  • // Accès à la ligne suivante, sous forme de tableau associatif
  • function ligneSuivante ($resultat) {}
  • // Accès à la ligne suivante, sous forme de tableau indicé
  • function tableauSuivant ($resultat) {}
  • // Renvoie nombre de ligne de la requête
  • function nbLigne($resultat){}
  • // Echappement des apostrophes et autres préparations à l'insertion
  • function prepareChaine($chaine) {}
  • // Acesseur pour les propirétés propore à chaque SGBD
  • // Nom du SGBD
  • function getSGBD()
  • {
  • return $this->sgbd;
  • }
  • function setSGBD($sgbd)
  • {
  • $this->sgbd = $sgbd;
  • }
  • // Code erreur du SGBD
  • function getCodeErreur()
  • {
  • return $this->codeErreur;
  • }
  • function setCodeErreur($codeErreur)
  • {
  • $this->codeErreur = $codeErreur;
  • }
  • // Message d'erreur du SGBD
  • function getMessErreur()
  • {
  • return $this->messErreur;
  • }
  • function setMessErreur($messErreur)
  • {
  • $this->messErreur = $messErreur;
  • }
  • // Fin de la classe
  • }
  • ?>
  • <?php
  • // Sous-classe de la classe abstraite BASE, pour l'accès à MySQL
  • require_once("base.class.php");
  • class BASE_MYSQL extends BASE
  • {
  • // Pas de propriétés ou de constructeur: ils sont héritées de la classe BASE
  • // Partie privée: surcharge des méthodes
  • // Méthode connect: connexion à MySQL
  • function connect($login, $mdp, $base, $serveur)
  • {
  • // Connexion au serveur MySQL
  • if (!$this -> connexion = @mysql_pconnect($serveur, $login, $mdp) or !@mysql_select_db($base, $this->connexion))
  • {
  • $this -> sgbd = "MySQL";
  • $this -> defErreur();
  • return false;
  • }
  • else
  • {
  • return $this -> connexion;
  • }
  • }
  • // Méthode d'exécution d'une requête.
  • function exe ($requete)
  • {
  • if (!$resultat = @mysql_query ($requete, $this -> connexion))
  • {
  • $this -> defErreur();
  • return false;
  • }
  • else
  • {
  • return $resultat;
  • }
  • }
  • // Méthode defErreur: détermine les codes d'erreurs propres à MySQL
  • function defErreur()
  • {
  • $this -> messErreur = mysql_error();
  • $this -> codeErreur = mysql_errno();
  • }
  • // Partie publique: surcharge des méthodes abstraites
  • // Accès à la ligne suivante, sous forme d'objet
  • function objetSuivant($resultat)
  • { return mysql_fetch_object($resultat); }
  • // Accès à la ligne suivante, sous forme de tableau associatif
  • function ligneSuivante($resultat)
  • { return mysql_fetch_assoc($resultat); }
  • // Accès à la ligne suivante, sous forme de tableau indicé
  • function tableauSuivant($resultat)
  • { return mysql_fetch_row($resultat); }
  • // Renvoie nombre de ligne de la requête
  • function nbLigne($resultat)
  • { return mysql_num_rows($resultat); }
  • // Echappement des apostrophes pour préparation à l'insertion ou à consultation
  • function prepareChaine($chaine)
  • { return mysql_real_escape_string($chaine); }
  • // Destructeur de la classe: on se déconnecte
  • function __destruct ()
  • {
  • if (!$this -> connexion = @mysql_close ($this->connexion))
  • return false;
  • }
  • // Fin de la classe
  • }
  • ?>
  • // Fonctions pour connexion à la base en fonction du SGBD
  • // arguments par valeur : $login, $passe, $base, $serveur -> paramètre de connexion à la base
  • // arguments par adresse : aucun
  • // retourne : $bd -> objet intance de la sous-classe utilisée
  • function connexion ($login, $mdp, $base, $serveur)
  • {
  • define ("SGBD", "MySQL"); // A definir en fonction du SGBD utilisé
  • // Instanciation d'un objet instance de BASE.
  • // Choix de la sous-classe en fonction du SGBD
  • switch (SGBD)
  • {
  • case "PostgreSQL":
  • $bd = new BASE_POSTGRESQL ($login, $mdp, $base, $serveur); // Exemple à definir
  • break;
  • case "SQLite":
  • $bd = new BASE_SQLITE ($login, $mdp, $base, $serveur); // Exemple à definir
  • break;
  • default: // MySQL par défaut
  • $bd = new BASE_MYSQL ($login, $mdp, $base, $serveur);
  • break;
  • }
  • return $bd;
  • }
<?php
// Classe abstraite définissant une interface générique d'accès à une base de données

 class BASE
{
  // propriétés protégée
  var $connexion;
  var $messExplicatif;
  var $codeErreur;
  var $messErreur;
  var $SGBD;
  
  // Constructeur de la classe
  function BASE($login, $motDePasse, $base, $serveur)
  {
    // Initialisations
    $this -> messExplicatif = "";
    $this -> codeErreur = 0;
    $this -> messErreur = "";
    $this -> sgbd = "Indefini";
    
    // Connexion au serveur par appel à une méthode privée
    if (!$this -> connexion = $this->connect($login, $motDePasse, $base, $serveur))
    {
      $this -> messExplicatif = "Erreur de connexion au SGBD " . $this->sgbd . ": <BR> " . $this->messageSGBD();
    }
  }
  // Fin du constructeur


  // Méthodes privées
  // Méthodes abstraites
  function connect($login, $motDePasse, $base, $serveur) {}
  function exe ($requete) {}
  // Méthode de mise en forme du message d'erreur du SGBD
  function messageSGBD ()
  {
    return "Libelle erreur : ".$this->messErreur."<BR />Num erreur :".$this->codeErreur;
  }


  // Méthodes publiques
  // Méthode d'exécution d'une requête
   function exeRequete ($requete)
  {
    if (!$resultat = $this -> exe ($requete))
    {
      $this -> messExplicatif = "Problème dans l'exécution de la requête : " . $requete . "<BR> " . $this->messageSGBD();
    }
    else
    {
      return $resultat;
    }
  }
  // Retour du message d'erreur
  function messageExplicatif ()
  { 
    return $this->messExplicatif; 
  }

  // Méthodes abstraites
  // Accès à la ligne suivante, sous forme d'objet
  function objetSuivant ($resultat) {}
  // Accès à la ligne suivante, sous forme de tableau associatif
  function ligneSuivante ($resultat) {}
  // Accès à la ligne suivante, sous forme de tableau indicé
  function tableauSuivant ($resultat) {}
  // Renvoie nombre de ligne de la requête
  function nbLigne($resultat){}
  // Echappement des apostrophes et autres préparations à l'insertion
  function prepareChaine($chaine) {}

  // Acesseur pour les propirétés propore à chaque SGBD
  // Nom du SGBD
  function getSGBD()
  {
    return $this->sgbd;
  }
  function setSGBD($sgbd)
  { 
    $this->sgbd = $sgbd;
  }
  // Code erreur du SGBD
  function getCodeErreur()
  {
    return $this->codeErreur;
  }
  function setCodeErreur($codeErreur)
  {
    $this->codeErreur = $codeErreur;
  }
  // Message d'erreur du SGBD
  function getMessErreur()
  {
    return $this->messErreur;
  }
  function setMessErreur($messErreur)
  { 
    $this->messErreur = $messErreur;
  }
  // Fin de la classe
}
?>


<?php
// Sous-classe de la classe abstraite BASE, pour l'accès à MySQL

require_once("base.class.php");

class BASE_MYSQL extends BASE
{
  // Pas de propriétés ou de constructeur: ils sont héritées de la classe BASE


  // Partie privée: surcharge  des méthodes
  // Méthode connect: connexion à MySQL
   function connect($login, $mdp, $base, $serveur)
  {
    // Connexion au serveur MySQL
    if (!$this -> connexion = @mysql_pconnect($serveur, $login, $mdp) or !@mysql_select_db($base, $this->connexion))
    {
      $this -> sgbd = "MySQL";
      $this -> defErreur();
      return false;
    }
    else
    {
      return $this -> connexion;
    }
  }
  
  // Méthode d'exécution d'une requête.
  function exe ($requete)
  {
    if (!$resultat = @mysql_query ($requete, $this -> connexion))
    {
      $this -> defErreur();
      return false;
    }
    else
    {
      return $resultat;
    }
  }

  // Méthode defErreur: détermine les codes d'erreurs propres à MySQL
  function defErreur()
  {
    $this -> messErreur = mysql_error();
    $this -> codeErreur = mysql_errno();
  }


  // Partie publique: surcharge  des méthodes abstraites
  // Accès à la ligne suivante, sous forme d'objet
  function objetSuivant($resultat)
  { return mysql_fetch_object($resultat); }
  // Accès à la ligne suivante, sous forme de tableau associatif
  function ligneSuivante($resultat)
  { return mysql_fetch_assoc($resultat); }
  // Accès à la ligne suivante, sous forme de tableau indicé
  function tableauSuivant($resultat)
  { return mysql_fetch_row($resultat); }
  // Renvoie nombre de ligne de la requête
  function nbLigne($resultat)
  { return mysql_num_rows($resultat); }
  // Echappement des apostrophes pour préparation à l'insertion ou à consultation
  function prepareChaine($chaine)
  { return mysql_real_escape_string($chaine); }


  // Destructeur de la classe: on se déconnecte
  function __destruct ()
  {
    if (!$this -> connexion = @mysql_close ($this->connexion))
    return false;
  }
  // Fin de la classe
}
?>


// Fonctions pour connexion à la base en fonction du SGBD
// arguments par valeur : $login, $passe, $base, $serveur -> paramètre de connexion à la base
// arguments par adresse : aucun
// retourne : $bd -> objet intance de la sous-classe utilisée
function connexion ($login, $mdp, $base, $serveur)
{
  define ("SGBD", "MySQL"); // A definir en fonction du SGBD utilisé

  // Instanciation d'un objet instance de BASE.
  // Choix de la sous-classe en fonction du SGBD
  switch (SGBD)
    {
    case "PostgreSQL":
      $bd = new BASE_POSTGRESQL ($login, $mdp, $base, $serveur);   // Exemple à definir
      break;
 
    case "SQLite":
      $bd = new BASE_SQLITE ($login, $mdp, $base, $serveur);    // Exemple à definir
      break;

    default: // MySQL par défaut
      $bd = new BASE_MYSQL ($login, $mdp, $base, $serveur);
      break;
    }
  return $bd;
}

Conclusion

Voici un exemple simple d'utilisation

$base = connexion (NOM, MDP, BASE, SERVEUR);
$resultat = $base -> exeRequete ("SELECT * FROM Produit");

while ($obj = $base -> objetSuivant($resultat))
echo $obj -> nomPdt."<BR />";
  • signaler à un administrateur
    Commentaire de gr43 le 21/05/2008 15:35:51

    N'hésiter pas à corriger mes erreurs. Merci

  • signaler à un administrateur
    Commentaire de depression le 21/05/2008 15:41:40

    Je te rappelle que PHP4 est mort...

  • signaler à un administrateur
    Commentaire de malalam le 21/05/2008 19:39:25 administrateur CS

    Hello,

    je suis embêté pour commenter ton code. Je pense la même chose que Dépression. Déjà.
    Ensuite, il est vraiment très basique. Je pourrais louer le débutant qui fait de l'abstraction en php4. La base est bonne. Il y a pas mal de problèmes quand même.
    Bon...vaguement, je ne vais pas m'éterniser :
    - tu manques de constance dans l'écriture du code : choisis entre le français et l'anglais!
    - ton code balancera les erreurs PHP de toute manière selon l'error_reporting, dans certains cas. Pas dans d'autres. Cela rejoint le manque de constance.
    - avec juste un <br> tu parviens à nous imposer du html 3.2 à l'heure du xhtml...c'est quand même dommage. C'était pas la mort d'écrire <br /> au lieu de <BR>...
    - mysql_pconnect()...et si je ne veux pas de connexion persistante, je fais quoi...? Je modifie ta classe? A quoi bon faire de l'objet dans ce cas ? Une classe d'abstraction DB doit au moins donner un choix. Tu n'en donnes aucun.
    - ta classe ne fait qu'envelopper des fonctions existantes : elle ne propose rien de nouveau, ni aucune facilité. Si au moins tu nous proposais différentes DB, mais là en l'occurence, non, il faut les coder soi-même. Dans ce cas, tu aurais pu au moins donner quelques fonctionnalités nouvelles, nous permettre de faire en un appel ce qui prend plusieurs lignes de code sans classe (renvoyer la clef primaire d'une table par exemple ? Chercher si une table existe ? Une bdd ? Un champ ? etc...).

    Bref...ce n'est pas MAL codé. C'est propre, ça va. C'est correct, quoi. Mais ça n'apporte vraiment rien. Pas même à toi, à part le plaisir de le coder et du coup de t'améliorer. Mais à nous...? Rien.
    Tu devrais approfondir, vraiment beaucoup. Et même si ton but n'est que de t'améliorer et d'avoir des critiques : vas plus loin...parce que là le code est tellement basique qu'il n'y a pas grand chose à en dire : c'est ok. Voilà. En même temps, tu n'as pas pris de risque.

  • signaler à un administrateur
    Commentaire de gr43 le 21/05/2008 20:21:53

    Merci pour vos commentaires.

    Pour le php4 je n'est pas le choix vu le serveur.
    Pour le <BR /> tu es dur car il y en un sur 2. C'est un de trop c'est vrai. Par contre pour le reste tu as tout à fait raison et je m'y attèle de ce pas. Je voulais juste savoir si je n'avais pas fait d'erreur de syntaxe car je débute en POO et PHP4 c'est un peu la m...
    J'aurrai peut être dû la poster en forum, désolé.

    Pour les erreurs avec une gestion personnalisée en PHP4, est on obligé de les avoirs, à part en modifiant les E_WARNING ou avec un debug_backtrace() dans la fonction car les @ ne suffisent pas ou encore en stoppant temporairement la gestion perso? Je ne vois comment faire autrement car pas d'exception.

    Merci encore.

  • signaler à un administrateur
    Commentaire de malalam le 21/05/2008 20:29:21 administrateur CS

    Je voulais dire pour les erreurs que parfois tu mets un @ (qui masque l'erreur, et tu peux donc n'avoir QUE ton gestionnaire en action), parfois pas.
    Sinon, un vrai gestionnaire d'erreur personnalisée ferait l'affaire mais il ne doit pas être lié à ta classe. Il doit être global dans ce cas, donc c'est une autre source.

  • signaler à un administrateur
    Commentaire de depression le 21/05/2008 21:31:49

    Malalam, qu'est ce qu'il t'arrive?

    Comment ça se fait que tu n'aies pas parlé de PHP5.1 et de PDO?

    Je ne sais que dire...

  • signaler à un administrateur
    Commentaire de gr43 le 21/05/2008 21:36:52

    Il n'est pas lié à ma classe. Mais si je ne veux pas que les erreurs comme une indisponibilité du SGBD ne soient pas toujours prises en charge par mon gestionnaire, dans certains traitements comme la validation d'une commande par exemple, comment faire? (restore_error_handler, debug_backtrace(), variable globale..., n'y a t'il pas d'autres moyens plus propres comme la gestion des exceptions de php5) Les exceptions  
    ne terminent pas un script mais elles permettent un traitement  particulier, non? Désolé de te prendre la tête des deux côtés (forum et sources).

  • signaler à un administrateur
    Commentaire de malalam le 21/05/2008 21:59:20 administrateur CS

    J'ai parlé de PHP 5 (en disant que j'étais d'accord avec toi, c'était sous-entendu lol), et PDO...c'est déhà uine abstraction, alors la réutiliser pour faire une surcouche, bof...mais s'en inspirer, un peu comme ADODB, ça oui :-) Mais bon, en PHP4 c'est moins facile déjà...

  • signaler à un administrateur
    Commentaire de malalam le 21/05/2008 22:03:13 administrateur CS

    @GR43 : ta classe n'est qu'une couche d'abstraction DB./..elle gère les erreurs DB. Dans le cadre d'une boutique avec prise de commande, ou d'un applicatif logistique... : l'applicatif gère les erreurs de l'abstraction DB et réagit en fonction. C'est plus facile avec les exceptions je suis d'accord. Totalement :-) Mais ça reste faisable en PHP4 en se contenant de renvoyer des true/false en fonctiopn de ce qu'il se passe. Et donc, en interceptant les erreurs de type warning, notice etc...donc en les masquant.

  • signaler à un administrateur
    Commentaire de gr43 le 21/05/2008 22:28:59

    Elle revoie bien des true/false, non?
    en tout cas merci de ses explications.

  • signaler à un administrateur
    Commentaire de depression le 21/05/2008 23:46:54

    @Malalam: (je viens de me rendre compte que ton pseudo est un palyndrôme)

    En fait, depuis PDO justement, je ne vois plus l'intérêt des classes d'abstraction justement, c'est ce que je voulais dire...

  • signaler à un administrateur
    Commentaire de malalam le 21/05/2008 23:57:08 administrateur CS

    Oui lol en effet, les gens le voient assez tard en général...quand ils le voient ;-)
    PDO ne répond pas à tout. C'est pour ça que sur ce code, j'insistais sur l'originalité des fonctionnalités. Si on doit faire une classe d'abstraction DB, il faut proposer des fonctionnalités, des simplifications sympas, utiles, et originales. Sinon en effet, autant utiliser PDO.

  • signaler à un administrateur
    Commentaire de coucou747 le 22/05/2008 07:42:48

    perso, PDO + multiton, et ca roule :)

    sinon, son code, je ne vois pas trop ce que tu lui reproches malalam. Enfin pour un code en php4, je vois difficilement comment faire mieux. Ce design :
    driverinterface (ou classe abstraite)
    drivermysql <---- driverinterface
    driverpostgre <---- driverinterface
    connections (driverinterface)

    c'est un classique

    bon, sauf que la, concection est une fonction alors qu'en general, connections est soit un singleton soit un muliton, (mais pas toujours une factory)

    sinon, renvoyer false, pour pouvoir faire un ===false, pour contourner les exceptions, c'est comme faire des monades. Et les monades sont des trucs que les gens font dans des langages propres pour eviter les Exceptions (Exception etant un effet de bord...)
    Mais en php, on a pas l'habitude de se preoccuper des effets de bords (surtout dans une classe comme celle-ci), donc les monades n'ont pas trop leur place.
    Bref, si tu pouvais utiliser les Exceptions, ca serait bien, mais si tu veux rester en php4, alors ca me semble une bonne solution...


    Bref, faire du php4 en 2008, c'est mauvais, mais pour du php4, moi je trouve que cette classe tient debout.

  • signaler à un administrateur
    Commentaire de malalam le 22/05/2008 10:58:27 administrateur CS

    Je l'ai dit ce que je reprochais : pas grand chose au niveau du code, mais pas mal au niveau des fonctionnalités. Une classe se contentant uniquement d'envelopper des fonctions existantes, ça n'a pas vraiment d'intérêt; il faut essayer de pousser plus loin.

  • signaler à un administrateur
    Commentaire de neigedhiver le 22/05/2008 11:36:28

    Salut,

    "Les exceptions  
    ne terminent pas un script mais elles permettent un traitement  particulier, non?"

    Si. Une exception termine un script. Elle ne redonne pas la main et NE DOIT PAS servir à effectuer un traitement différent du site.
    La règle numéro 2 énoncée par Markus Börger dans son document "SPL for the masses" dit :
    "Never use exceptions for control flow"
    http://somabo.de/talks/200504_php_quebec_spl_for_the_masses.pdf (page 38)

  • signaler à un administrateur
    Commentaire de malalam le 22/05/2008 12:39:41 administrateur CS

    C'est pas la question : dans les faits, une exception redonne la main. Tout ce qui se trouve après le catch sera exécuté. On en revient à la même discussion ;-) Si ce cher Marcus estime qu'un catch doit se trouver en fin de script, pourquoi PHP rend-il la main après un catch...? Une erreur fatale ne rend pas la main, parce qu'on estime que PHp est devenu instable et que ce serait dangereux.
    Dans le cas d'une exception, c'est différent... : on tombe sur un cas exceptionnel. Ce qui ne veut pas dire que tout doit s'arrêter : seulement le traitement que l'on essaye (d'où "try"). Je continue de penser que Marcus est équivoque dans ce qu'il dit, quand bien même dans les faits, mes catch sont généralement à la fin du script (j'ai rarement plus d'un traitement par script, en fait).

  • signaler à un administrateur
    Commentaire de neigedhiver le 22/05/2008 14:26:53

    Tiens... J'avais jamais remarqué que PHP redonnait la main... parce que, comme toi, mes catch sont en fin de script.

    Maintenant, si ce que Markus dit est équivoque, ce qu'il énonce reste quand même (à mon avis en tout cas) une règle de "best practice".
    Il y a ce que permet PHP techniquement et ce qui fait qu'un code est "bien codé".

  • signaler à un administrateur
    Commentaire de aKheNathOn le 01/06/2008 13:27:41

    Y'a un truc qui me géne, c'est le define ("SGBD", "MySQL"); a la ligne 190. Il ne devrait pas se trouver dans une fonction car il n'aimerais pas s'executer plusieurs fois ...

    Sinon ligne 33 / 34 tu pourrait mettre :
      function connect($login, $motDePasse, $base, $serveur) { trigger_error('You class must define a connect function !', E_USER_ERROR); }
      function exe ($requete) { trigger_error('You class must define a exe function !', E_USER_ERROR); }

    Cela ressemblerais un peu plus à de l'abstraction au cas où la classe ne serais pas construite correctement. Le désavantage c'est que l'erreur serais visible qu'à l'utilisation des fonctions...

  • signaler à un administrateur
    Commentaire de aKheNathOn le 01/06/2008 14:14:58

    Pour l'histoire d'abstraction j'ai essayé de monter un modèle plausible :
    http://www.phpcs.com/tutoriaux/ABSTRACTION-PHP_845.aspx

  • signaler à un administrateur
    Commentaire de gr43 le 03/06/2008 22:04:26

    En fait define ("SGBD", "MySQL") permet de modifier le sgbd utilisé sans modifier tous les appels qui sont fais dans les différents srcripts. Donc, si tu veux utiliser PostgreSQL par exemple, tu modifie simplement dans la fonction define ("SGBD", "PostgreSQL")et tu cré bien entendu la classe fille Postgre. De plus, tu as raison, cela fait une erreur si tu essaye d'ouvrir deux connexions puisque la variable est déjà déclarée mais ce qui est plutôt utile je trouve car je ne vois pas l'intérêt d'ouvrir plusieurs connexion différentes par script. Pour trigger_error, tu as raison mais j'ai fais en fait d'autre fonction qui réalise cela si impossibilité de se connecter ou d'executer la requête, ce qui me permet de ne pas lever d'erreur dans tous les cas mais d'interoger le résultat des méthodes pour ne pas stopper le script dans mon cas car mes E_USER_ERROR le stoppe dans mon gestionaire d'erreur. Merci de tes remarques, je vais aller voir ton travail. A plus..

  • signaler à un administrateur
    Commentaire de neigedhiver le 04/06/2008 11:37:30

    "je ne vois pas l'intérêt d'ouvrir plusieurs connexion différentes par script."

    Des fois, on a besoin de se connecter à plusieurs serveurs, parce que le fournisseur d'une entreprise n'a pas forcément envie de partager son serveur et sa base de données avec tous ses clients. C'est qu'un exemple...

  • signaler à un administrateur
    Commentaire de aKheNathOn le 04/06/2008 23:40:47

    De manière générale t'as une classe gérant la connexion. Si elle ne sert à être instanciée qu'une seule fois, c'est un singleton, or là ce n'en est pas un (mais c'est pas vraiment le pb).

    Tu développes en objet, donc tu dois avoir une approche objet donc une approche sur l'instanciation de ta classe. Dans ton modéle tu proposes une fonction, c'est pas forcément bon en POO.

    Tu aurais très bien pu créer une classe de type proxy, exploser un peu plus ton modéle...brèf améliorer ton modèle objet. Je te conseille de consulter le tuto de Malalam sur les design patterns il explique tout ça et c'est réalisable en PHP4.

    En tout cas dans l'état de ton code tu ne peux appeller qu'une seule fois la fonction de connexion et le type de base de données ne devrait pas être définit ainsi. Juste un exemple équivalent :

    class BASE {
    ...
      function load($base, $host = 'localhost', $user = 'root', $pwd = '', $type = 'mysql') {
        $class = 'BASE_'.$type;
        if (class_exists($class)) {
           return new $class($user, $pwd, $base, $host);
        } else {
           // GENERER UNE ERREUR
        }
      }
    ...
    }

    et au niveau utilisation ça donnerais :

    $dbMySQL = BASE::load('test', 'localhost', 'root', 'pwd', 'mysql');
    $dbPostGRE = BASE::load('test', 'localhost', 'root', 'pwd', 'postgre');
    ...etc...

    Bonne prog et a+,
    akh

  • signaler à un administrateur
    Commentaire de malalam le 04/06/2008 23:43:13 administrateur CS

    Hello,

    heu oui...travailler avec plusieurs connexions peut-être carrément nécessaire. Sans parler de différents serveurs (bien que ce soit aussi mon cas, comme pour Neige apparemment : synchroniser 2 serveurs DB, par exemple...), on peut aussi avoir un serveur, et plusieurs DB... et une connexion par DB avec chacune leurs droits (histoire d'éviter les truncate malheureux....).
    Non, jouer avec plusieurs connexions n'est peut-être pas une habitude dans le dév amateur, mais c'est carrément une quasi obligation dans le dév pro.

  • signaler à un administrateur
    Commentaire de malalam le 04/06/2008 23:47:41 administrateur CS

    ceci dit, ça n'enlève rien au principe du singleton suggéré par Akhenathon (entre autres choses); on peut juste le transformer en multiton. Mais bordel, 1 connexion, 1 instance...c'est un minimum syndical, certes...mais ne pas être limité à 1 connexion est vital.
    Pour l'interfaçage je rejoins Akhe, c'est facile à moindre frais, même en PHP4. Et c'est bien plus élégant comme son exemple le montre.

  • signaler à un administrateur
    Commentaire de gr43 le 09/06/2008 14:45:16

    Salut,
    C'est vrai que j'aime bien le principe de la fonction car elle permet de ne pas avoir à modifier les appels aux constructeurs dans les différents scripts lors de la migration vers un autre SGBD. Pour la gestion de plusieurs connexions on peut alors modifier la constante par une variable. Puis, on peut toujours utiliser un patterns.
    Par contre, je trouve ton exemple sympa puisqu'il permet d'obtenir une erreur si  on instancie un objet d'une classe inexistante. Merci de vos remarques, je vais me pencher sur les design patterns.

  • signaler à un administrateur
    Commentaire de aKheNathOn le 09/06/2008 19:06:31

    Lut, ru dis que tu aimes les fonctions car pas besoin de passer par un constructeur. Il me semble que tu ne connais pas vraiment l'appel de résolution de porté - un tuto à cette adresse :
    http://fr2.php.net/manual/fr/language.oop5.paamayim-nekudotayim.php

    Tu peux faire des fonctions statiques appellées sans instancier la classe ce qui permet d'encapsuler dans des classes des fonctions indépendantes. L'avatage c'est que quand tu lis ton code c'est plus lisible, et tu sais où trouver la fonction. Les singleton fonctionnent comme ça - un exemple en php 4 : http://zefredz.frimouvy.org/dotclear/index.php?2007/02/18/160-forcer-un-singleton-en-php4

    Un ptit commentaire pour la gestion des erreurs. Il serais préférable tu que généres tes erreurs à partir de la fonction trigger_error car elle est utilisée par le framework php - tu peux les logguer et bien plus. Du coup jettes un coup d'oeil sur http://fr2.php.net/manual/fr/function.set-error-handler.php, tu peux facilement faire un singleton gérant l'abstraction des erreurs générées par ta partie de code et les autres erreurs système. L'avantage est de centraliser la gestion des erreurs, voire même de la surcharger pour la spécialiser selon cas d'utilisation. Ca serait un réel plus par rapport à tout ce qui existe déjà.

    Bonne continuation

  • signaler à un administrateur
    Commentaire de gr43 le 10/06/2008 11:34:33

    Si je connais l'appel de résolution de porté, bien que je ne sois pas un expert. En fait, tu m'as convaincu il suffit de faire $base = BASE::load (NOM, MDP, BASE, SERVEUR, SGBD); et de modifier la constante SGBD en fonction de celui utilisé mais j'y avais pas réfléchi et je voulais pas devoir changer les appels à chaque script. Mais par contre, autant utilisé une factory pour permettre le chargement à la volée de la sous-classe utilisé, non?

    Pour les trigger_error, je vais potasser tout çà, en tous cas merci des liens car ils sont bien utiles. Je t'avoue que je suis un peu léger niveau connaissance.

    Si je peux me permettre une petite question, je ne vois pas trop la différence entre méthode à portée de classe et méthode privée?

    Merci encore de tes remarques constructives et à plus

  • signaler à un administrateur
    Commentaire de gr43 le 10/06/2008 11:38:29

    Par contre appelée la méthode load de façon static alors qu'elle n'est pas déclarée static car PHP4, cela me fait une erreur E_STRICT sur PHP5 que je peux éliminer dans mon gestionaire d'erreur avec debug_backtrace par exemple, mais c'est peut-être pas très propre. Si t'as une idée, mais bon c'est pas très grave. Bye

  • signaler à un administrateur
    Commentaire de neigedhiver le 10/06/2008 14:09:32

    Salut,

    "Mais par contre, autant utilisé une factory pour permettre le chargement à la volée de la sous-classe utilisé, non?'"
    Ca ne revient pas à ça, c'est exactement ça... La méthode statique load est la factory de ta classe dans ton cas.

    "Par contre appelée la méthode load de façon static alors qu'elle n'est pas déclarée static car PHP4, cela me fait une erreur E_STRICT sur PHP5"
    Autant écrire une classe PHP4 et une classe PHP5... Quitte à utiliser PHP5, autant l'utiliser pour de vrai, plutôt que de se limiter à une utilisation archaïque.

  • signaler à un administrateur
    Commentaire de gr43 le 10/06/2008 18:20:53

    Hello,
    je pensais à une factory du type :(vue sur php.net)
    class Exemple
    {
        // La méthode de paramètre d'usine
        public static function factory($type)
        {
            if (include_once 'Drivers/' . $type . '.php') {
                $classname = 'Driver_' . $type;
                return new $classname;
            } else {
                throw new Exception ('Driver non trouvé');
            }
        }
    }
    Ce qui m'éviterai d'inclure les différentes classes dans mon fichier d'inclusion mais seulement la classe mère, elle même se chargeant de charger le driver du sgbd souhaité lors d'une instanciation.
    Ouais, désolé je plane pour E_STRCIT mais c'est par ce qu'en local (je suis quand même pas tout à fait maso), je suis en PHP5 mais le serveur est en PHP5. Mais j'essaye de coder avec le moins de syntaxe obsolète possible... (je sais bonne blague pour du PHP4).

  • signaler à un administrateur
    Commentaire de gr43 le 10/06/2008 18:25:43

    Je veux dire, le serveur est en PHP4, il va me rendre fou.
    Tchao

  • signaler à un administrateur
    Commentaire de neigedhiver le 11/06/2008 12:16:58

    Ca dépend de ce que tu appelles une factory...
    Pour moi, c'est au minimum une méthode statique. Mais ça pourrait aussi être une classe statique.

    $base = BASE::load (NOM, MDP, BASE, SERVEUR, SGBD);

    La méthode statique load est une factory : c'est elle qui va instancier la bonne classe en fonction de ce que tu lui demandes.

    "je suis en PHP5 mais le serveur est en PHP4"

    T'as pas à avoir honte : je suis dans le même cas, au boulot (on choisit pas tout, et surtout, faire des mises à jours aussi importantes sur plusieurs serveurs en prod, ça nécessite de faire quelques tests, et pour ça, faut avoir du temps)

  • signaler à un administrateur
    Commentaire de gr43 le 11/06/2008 13:47:29

    Merci, à tous de vos commentaire, c'est sympa de pouvoir confronter ses idées et c'est comme ça que l'on apprend.
    A plus

Ajouter un commentaire

Discussions en rapport avec ce code source

Pub



Appels d'offres

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS