begin process at 2012 02 15 06:34:48
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Class et Objet ( POO )

 > CLASSE PHP4 DE CONNEXION À UN SGBD

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 />";


 Sources de la même categorie

CLASSE DE GESTION DE "VARIABLES GLOBALES D'ENVIRONNEMENT" par pifou25
Source avec Zip COLLECTION.CLASS.MIN.PHP par thunderhunter
Source avec Zip SIMPLETEMPLATE par thunderhunter
Source avec Zip Source avec une capture VOIR QUI VISITE VOTRE SITE par Dariumis
Source avec Zip CLASS SIMPLE CBASEDONNEE par smag42

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture SYSTEME D'AUTHENTIFICATION PHP AVEC PROTÉCTION KEYLOGGER par mtrix000
Source avec Zip Source avec une capture TODO LIST (AJAX/PHP5) par VinceMonkeyz
Source avec Zip CLIENT / SERVEUR : LES SOCKETS par Morphinof
Source avec Zip MYGGL GOOGLE API CLASS FOR BEGINERZ par lezj
Source avec Zip Source avec une capture LOGIN SHA1 + CRÉATION UTILISATEUR par aventurier19

Commentaires et avis

Commentaire de gr43 le 21/05/2008 15:35:51

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

Commentaire de depression le 21/05/2008 15:41:40

Je te rappelle que PHP4 est mort...

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.

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.

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.

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...

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).

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à...

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.

Commentaire de gr43 le 21/05/2008 22:28:59

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

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...

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.

Commentaire de coucou747 le 22/05/2008 07:42:48 administrateur CS

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.

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.

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)

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).

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é".

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...

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

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..

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...

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

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.

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.

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.

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

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

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

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.

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).

Commentaire de gr43 le 10/06/2008 18:25:43

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

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)

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 dans le forum

php 3 et php4 [ par php ] C'est quoi la difference de php 3 et de php 4 ? redirection [ par ouiouiteur ] comment rediriger une page vers :-soit une page sur mon serveur chez moi, si ma connexion est active-soit vers une page sur un hebergeur gratuit pour Connexion ki ve pas ?!? [ par FF.ST Hébergement ] Je tente de me connecter à un serveur counter-strike ...Pas de pot, ça marche pas !Pourtant la connexion de counter strike est une cnx normale TCP sur Comment faire ? Connexion TCP ki ve pas [ par FF.ST Hébergement ] Je tente de me connecter à l'aide de fsockopen sur un serveur counter-strike (half life).La connexion ne marche pas :(Pk ?$cnx = fsockopen("24.120.30. Hébergeur ASP/PHP4 [ par xav ] J'ai trouvé un hébergeur qui fait de l'asp/php4, c'est webcentrale.com. Leurs prix sont tout à fait raisonnables et je suis vraiment très content de l Nom de variable... [ par RockmanX ] Voilà,j'ai un fichier que je vais appeler form.php4 qui contient 1 input : &lt;INPUT TYPE='text' NAME='quantite".$idarticle."' VALUE='".$nbrarticle."' Connexion à une base de données Paradox ! [ par orelien ] Bonjour !Voilà, j'aimerai me connecter à une base de données Paradox mais je n'y arrive pas !...Quelqu'un peut il m'aider ??Merci beaucoup.Orelien. connexion avec sql server [ par mabrouk ] bonjour, svp je travaille sur un poste client windows2000 server dans un domaine j'ai installé easyphp(php+apache+mysql), j'ai voulu se connecter a no Connexion telnet [ par Ark1 ] Bijour all,J'aimerais savoir si il est possible de se connecter a un serveur telnet, si oui pourrait on me donner une pitite liste des fonction a util


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,106 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales