Overview

Packages

  • Framework
  • None
  • PHP
  • Utilitaire

Classes

  • Bdd
  • Cache
  • CacheSimple
  • Chronometre
  • Cli
  • Config
  • Controleur
  • Debug
  • Framework
  • GestionnaireException
  • I18n
  • Log
  • Registre
  • RestClient
  • RestServeur
  • RestService
  • Script
  • SquelettePhp
  • Url
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: // declare(encoding='UTF-8');
  3: /**
  4:  * Classe Bdd, d'accés au base de données.
  5:  * Elle fait office d'abstraction légère de base de données en utilisant diverses possibilités d'accès aux
  6:  * bases de données (PDO, mysql, mysqli, SQLite3).
  7:  * Les valeurs pour le paramètre 'bdd_abstraction' du fichier config.ini sont : pdo, mysql, mysqli, sqlite3
  8:  * Vous pouvez aussi utiliser : "php:Bdd::ABSTRACTION_PDO","php:Bdd::ABSTRACTION_MYSQL", "php:Bdd::ABSTRACTION_MYSQLI",
  9:  * "php:Bdd::ABSTRACTION_SQLITE3".
 10:  * Elle peut être étendue, pour ajouter le support d'autres bases de données où prendre en compte des méthodes spécifique à
 11:  * un type d'abstraction.
 12:  *
 13:  * @category    php 5.2
 14:  * @package Framework
 15:  * @author      Aurélien PERONNET <aurelien@tela-botanica.org>
 16:  * @author      Jean-Pascal MILCENT <jpm@tela-botanica.org>
 17:  * @copyright   Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
 18:  * @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
 19:  * @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
 20:  */
 21: class Bdd {
 22:     /** Constante stockant le squelette du message en cas d'erreur de requête sql. */
 23:     const ERREUR_REQUETE_TPL = 'Requête echec.\nFichier : %s.\nLigne : %s.\nMessage : %s.\nRequête : %s';
 24: 
 25:     /** Constante stockant le squelette du message en cas d'erreur de connexion à la base de données. */
 26:     const ERREUR_CONNEXION_TPL = 'Erreur de connexion à la base de données, vérifiez les paramètres du fichier de configuration.\nMessage : %S.';
 27: 
 28:     /** Constante stockant le squelette du message en cas d'erreur de sélection de la base de données. */
 29:     const ERREUR_SELECTION_BDD_TPL = 'Erreur de sélection de la base de données, vérifiez les paramètres du fichier de configuration.\nMessage : %S.';
 30: 
 31:     /** Constante stockant le code pour l'abstraction de PDO. */
 32:     const ABSTRACTION_PDO = 'pdo';
 33: 
 34:     /** Constante stockant le code pour l'abstraction de mysql. */
 35:     const ABSTRACTION_MYSQL = 'mysql';
 36: 
 37:     /** Constante stockant le code pour l'abstraction de mysqli. */
 38:     const ABSTRACTION_MYSQLI = 'mysqli';
 39: 
 40:     /** Constante stockant le code pour l'abstraction de SQLite3. */
 41:     const ABSTRACTION_SQLITE3 = 'sqlite3';
 42: 
 43:     /** Constante stockant le code pour le mode tableau associatif des résultats des requêtes. */
 44:     const MODE_ASSOC = 'ASSOC';
 45: 
 46:     /** Constante stockant le code pour le mode objet des résultats des requêtes. */
 47:     const MODE_OBJET = 'OBJECT';
 48: 
 49:     /** Mode de fetch associatif */
 50:     protected $ASSOC = '';
 51: 
 52:     /** Mode de fetch objet */
 53:     protected $OBJECT = '';
 54: 
 55:     /** abstraction de base de données utilisée */
 56:     protected $abstraction;
 57: 
 58:     /** DSN pour accéder à la base de données */
 59:     protected $dsn;
 60: 
 61:     /** Type de base de données (mysql, mysqli, etc ...) */
 62:     protected $type;
 63: 
 64:     /** Hote herbergeant la base de données */
 65:     protected $hote;
 66: 
 67:     /** Nom de la base de données à laquelle le modèle doit se connecter */
 68:     protected $bdd_nom;
 69: 
 70:     /** Nom d'utilisateur */
 71:     protected $utilisateur;
 72: 
 73:     /** Mot de passe */
 74:     protected $pass;
 75: 
 76:     /** Encodage de la base de données */
 77:     protected $encodage = null;
 78: 
 79:     /** Connexion à la base de données */
 80:     protected $connexion = null;
 81: 
 82:     /** Tableau des noms des paramètres à définir dans le fichier de config car obligatoirement nécessaire à cette classe.*/
 83:     protected $parametres_obligatoires = array('bdd_abstraction', 'bdd_protocole', 'bdd_serveur', 'bdd_nom',
 84:         'bdd_utilisateur', 'bdd_mot_de_passe', 'bdd_encodage');
 85: 
 86:     /** Constructeur par défaut, appelé à l'initialisation. */
 87:     public function __construct() {
 88:         Config::verifierPresenceParametres($this->parametres_obligatoires);
 89:         $this->abstraction = strtolower(Config::get('bdd_abstraction'));
 90:         $this->type = Config::get('bdd_protocole');
 91:         $this->hote = Config::get('bdd_serveur');
 92:         $this->bdd_nom = Config::get('bdd_nom');
 93:         $this->utilisateur = Config::get('bdd_utilisateur');
 94:         $this->pass = Config::get('bdd_mot_de_passe');
 95:         $this->encodage = Config::get('bdd_encodage');
 96: 
 97:         if ($this->type == 'sqlite' || $this->type == 'sqlite2') {
 98:             $this->dsn = $this->type.':'.$this->hote;
 99:         } else {
100:             $this->dsn = $this->type.':dbname='.$this->bdd_nom.';host='.$this->hote;
101:         }
102:         $this->initialiserProtocole();
103:     }
104: 
105:     /** Initialise les constantes de classe à leur bonne valeur et déclenche une erreur si le protocole n'est pas bien défini. */
106:     protected function initialiserProtocole() {
107:         switch ($this->abstraction) {
108:             case self::ABSTRACTION_PDO :
109:                 $this->ASSOC = PDO::FETCH_ASSOC;
110:                 $this->OBJECT = PDO::FETCH_OBJ;
111:                 break;
112:             case self::ABSTRACTION_MYSQL :
113:                 $this->ASSOC = 'mysql_fetch_assoc';
114:                 $this->OBJECT = 'mysql_fetch_object';
115:                 break;
116:             case self::ABSTRACTION_MYSQLI :
117:                 $this->ASSOC = 'fetch_assoc';
118:                 $this->OBJECT = 'fetch_object';
119:                 break;
120:             case self::ABSTRACTION_SQLITE3 :
121:                 $this->ASSOC = 'SQLITE3_ASSOC';
122:                 $this->OBJECT = 'SQLITE3_OBJECT';
123:                 break;
124:             default:
125:                 $m = "Erreur : l'abstraction '{$this->abstraction}' n'est pas prise en charge";
126:                 trigger_error($m, E_USER_WARNING);
127:         }
128:     }
129: 
130:     /**
131:      * Connection à la base de données en utilisant les informations fournies par
132:      * le fichier de configuration.
133:      * Cette méthode est private et final car elle n'a pas vocation a être appelée par l'utilisateur.
134:      * TODO : il est peut être nécessaire pour MYSQL, MYSQLi et SQLITE3 afin d'éviter les boucles infinis
135:      * d'erreur quand la bdd n'est pas configuré d'utiliser : $this->connexion->query (comme pour PDO)
136:      */
137:     protected function connecter() {
138:         if ($this->connexion == null) {
139:             switch ($this->abstraction) {
140:                 case self::ABSTRACTION_PDO :
141:                     try {
142:                         $this->connexion = new PDO($this->dsn, $this->utilisateur, $this->pass);
143:                         $this->connexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
144:                     } catch (PDOException $e) {
145:                         $e = sprintf(self::ERREUR_CONNEXION_TPL, $e->getMessage());
146:                         trigger_error($e, E_USER_WARNING);
147:                     }
148:                     if ($this->encodage != null && $this->type == 'mysql') {
149:                         $this->connexion->query("SET names '".$this->encodage."'");
150:                     } else if ($this->type == 'sqlite') {
151:                         $this->connexion->query("PRAGMA case_sensitive_like = false");
152:                     }
153:                     break;
154:                 case self::ABSTRACTION_MYSQL :
155:                     $this->connexion = mysql_connect($this->hote, $this->utilisateur, $this->pass);
156:                     if ($this->connexion !== false) {
157:                         $selection = mysql_select_db($this->bdd_nom, $this->connexion);
158:                         if ($selection === false) {
159:                             $e = sprintf(self::ERREUR_SELECTION_BDD_TPL, mysql_error());
160:                             trigger_error($e, E_USER_WARNING);
161:                         }
162:                     } else {
163:                         $e = sprintf(self::ERREUR_CONNEXION_TPL, mysql_error());
164:                         trigger_error($e, E_USER_WARNING);
165:                     }
166:                     if ($this->encodage != null) {
167:                         $this->requeter("SET names '".$this->encodage."'");
168:                     }
169:                     break;
170:                 case self::ABSTRACTION_MYSQLI :
171:                     $this->connexion = @new mysqli($this->hote, $this->utilisateur, $this->pass, $this->bdd_nom);
172:                     if ($this->connexion->connect_errno) {
173:                         $e = sprintf(self::ERREUR_CONNEXION_TPL, $this->connexion->connect_error);
174:                         trigger_error($e, E_USER_WARNING);
175:                     }
176:                     if ($this->encodage != null) {
177:                         $this->requeter("SET names '".$this->encodage."'");
178:                     }
179:                     break;
180:                 case self::ABSTRACTION_SQLITE3 :
181:                     // cas particulier de sqllite, on considère que le nom de la base de données correspond au fichier à ouvrir
182:                     $this->connexion = new SQLite3($this->bdd_nom);
183:                     if (!$this->connexion) {
184:                         $e = sprintf(self::ERREUR_CONNEXION_TPL, '');
185:                         trigger_error($e, E_USER_WARNING);
186:                     }
187:                     $this->requeter("PRAGMA case_sensitive_like = false");
188:                     break;
189:                 default:
190:                     $this->connexion = null;
191:             }
192:         }
193:     }
194: 
195:     /**
196:      * Permet de tester, puis de reconnecter une connection au cas ou celle aurait été
197:      * perdue (utile dans le cas d'une connection ouverte depuis trop longtemps)
198:      * @return boolean
199:      */
200:     public function ping() {
201:         try {
202:             // requête très simple qui ne teste que l'activité de la connection
203:             $requete = 'SELECT 1';
204:             switch ($this->abstraction) {
205:                 case self::ABSTRACTION_PDO :
206:                         $retour = $this->connexion->query($requete);
207:                     break;
208:                 case self::ABSTRACTION_MYSQL :
209:                     $retour = mysql_query($requete, $this->connexion);
210:                     break;
211:                 case self::ABSTRACTION_MYSQLI :
212:                     $retour = $this->connexion->query($requete);
213:                     break;
214:                 case self::ABSTRACTION_SQLITE3 :
215:                     $retour = $this->connexion->exec($requete);
216:                     break;
217:             }
218:         } catch (PDOException $e) {
219:             $this->connecter();
220:         }
221:         return true;
222:     }
223: 
224:     /**
225:      * @deprecated changement de nom. Disparaîtra dans la version 0.4. Utiliser à la place : @see requeter
226:      */
227:     final protected function requete($requete) {
228:         return $this->requeter($requete);
229:     }
230: 
231:     /**
232:      * Execute une requête et retourne le résultat tel que renvoyé par l'abstraction courante.
233:      *
234:      * @param string la requête à effectuer
235:      * @return mixed un objet contenant le résultat de la requête
236:      */
237:     public function requeter($requete) {
238:         $this->connecter();
239: 
240:         $retour = null;
241:         switch ($this->abstraction) {
242:             case self::ABSTRACTION_PDO :
243:                 try {
244:                     $retour = $this->connexion->query($requete);
245:                 } catch (PDOException $e) {
246:                     $m = sprintf(self::ERREUR_REQUETE_TPL, $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
247:                     trigger_error($m, E_USER_WARNING);
248:                 }
249:                 break;
250:             case self::ABSTRACTION_MYSQL :
251:                 $retour = mysql_query($requete, $this->connexion);
252:                 break;
253:             case self::ABSTRACTION_MYSQLI :
254:                 $retour = $this->connexion->query($requete);
255:                 break;
256:             case self::ABSTRACTION_SQLITE3 :
257:                 $retour = $this->connexion->exec($requete);
258:                 break;
259:         }
260:         return $retour;
261:     }
262: 
263:     /**
264:      * @deprecated changement de nom. Disparaîtra dans la version 0.4. Utiliser à la place : @see recuperer
265:      */
266:     final protected function requeteUn($requete, $mode = self::MODE_ASSOC) {
267:         return $this->recuperer($requete, $mode);
268:     }
269: 
270:     /**
271:      * Execute une requête et retourne le premier résultat sous forme de tableau (par défaut) ou d'objet.
272:      * Les noms des champs de la base de données correspondent aux noms des clés du tableau ou aux noms des attributs de l'objet.
273:      *
274:      * @param string la requête à effectuer
275:      * @param string le mode de retour ASSOC (Bdd::MODE_ASSOC) pour un tableau ou OBJECT (Bdd::MODE_OBJET) pour un objet.
276:      * @return mixed un objet ou un tableau contenant le résultat de la requête
277:      */
278:     public function recuperer($requete, $mode = self::MODE_ASSOC) {
279:         $this->connecter();
280: 
281:         $retour = null;
282:         switch ($this->abstraction) {
283:             case self::ABSTRACTION_PDO :
284:                 try {
285:                     $resultat = $this->connexion->query($requete);
286:                     $retour = ($resultat !== false) ? $resultat->fetch($this->$mode) : $resultat;
287:                 } catch (PDOException $e) {
288:                     $m = sprintf(self::ERREUR_REQUETE_TPL, $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
289:                     trigger_error($m, E_USER_WARNING);
290:                 }
291:                 break;
292:             case self::ABSTRACTION_MYSQL :
293:                 $res = mysql_query($requete, $this->connexion);
294:                 $fonction_fetch = $this->$mode;
295:                 $retour = $fonction_fetch($res);
296:                 break;
297:             case self::ABSTRACTION_MYSQLI :
298:                 $res = $this->connexion->query($requete);
299:                 $fonction_fetch = $this->$mode;
300:                 $retour = $res->$fonction_fetch();
301:                 break;
302:             case self::ABSTRACTION_SQLITE3 :
303:                 $retour = $this->connexion->querySingle($requete);
304:                 break;
305:         }
306:         return $retour;
307:     }
308: 
309:     /**
310:      * @deprecated changement de nom. Disparaîtra dans la version 0.4. Utiliser à la place : @see recupererTous
311:      */
312:     final protected function requeteTous($requete, $mode = self::MODE_ASSOC) {
313:         return $this->recupererTous($requete, $mode);
314:     }
315: 
316:     /**
317:      * Execute une requête et retourne un tableau de résultats. Un résultat peut être présentés sous forme
318:      * de tableau (par défaut) ou d'objet.
319:      * Les noms des champs de la base de données correspondent aux noms des clés du tableau résultat ou
320:      * aux noms des attributs de l'objet résultat.
321:      *
322:      * @param string la requête à effectuer
323:      * @param string le mode de retour des résultats : ASSOC (Bdd::MODE_ASSOC) pour un tableau ou OBJECT (Bdd::MODE_OBJET) pour un objet.
324:      * @return array un tableau contenant les résultats sous forme d'objets ou de tableau (par défaut).
325:      */
326:     public function recupererTous($requete, $mode = self::MODE_ASSOC) {
327:         $this->connecter();
328: 
329:         $retour = null;
330:         switch ($this->abstraction) {
331:             case self::ABSTRACTION_PDO :
332:                 try {
333:                     $resultat = $this->connexion->query($requete);
334:                     $retour = ($resultat !== false) ? $resultat->fetchAll($this->$mode) : $resultat;
335:                 } catch (PDOException $e) {
336:                     $m = sprintf(self::ERREUR_REQUETE_TPL, $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
337:                     trigger_error($m, E_USER_WARNING);
338:                 }
339:                 break;
340:             case self::ABSTRACTION_MYSQL :
341:                 $resultat = mysql_query($requete, $this->connexion);
342:                 $fonction_fetch = $this->$mode;
343:                 while ($ligne = $fonction_fetch($resultat)) {
344:                     $retour[] = $ligne;
345:                 }
346:                 break;
347:             case self::ABSTRACTION_MYSQLI :
348:                 $resultat = $this->connexion->query($requete);
349:                 $function_fetch = $this->$mode;
350:                 while ($ligne = $resultat->$function_fetch()) {
351:                     $retour[] = $ligne;
352:                 }
353:                 break;
354:             case self::ABSTRACTION_SQLITE3 :
355:                 $resultat = $this->connexion->query($requete);
356:                 while ($ligne = $resultat->fetch_array($this->ASSOC)) {
357:                     if ($mode == self::MODE_OBJET) {
358:                         // Cas particulier de sqllite qui n'a pas de fonction fetch_object
359:                         $ligneObjet = new stdClass();
360:                         foreach ($ligne as $colonne => $valeur) {
361:                             $ligneObjet->$colonne = $valeur;
362:                         }
363:                         $ligne = $ligneObjet;
364:                     }
365:                     $retour[] = $ligne;
366:                 }
367:                 break;
368:         }
369:         return $retour;
370:     }
371: 
372:     /**
373:      * Protège une chaine de caractères ou le contenu d'un tablea avant l'insertion dans la base de données
374:      * (ajout de quotes ou guillemets).
375:      * @param Mixed une chaine ou un tableau à protéger
376:      * @return mixed la chaine ou le tableau à protégé
377:      */
378:     public function proteger($donnees) {
379:         $this->connecter();
380:         if (is_array($donnees)) {
381:             $retour = $this->protegerTableau($donnees);
382:         } else {
383:             $retour = $this->protegerChaine($donnees);
384:         }
385:         return $retour;
386:     }
387: 
388:     /**
389:      * Protège une chaine de caractères avant l'insertion dans la base de données (ajout de quotes ou guillemets).
390:      * @param string la chaine à protéger
391:      * @return string la chaine protégée
392:      */
393:     private function protegerChaine($chaine) {
394:         $retour = $chaine;
395:         switch ($this->abstraction) {
396:             case self::ABSTRACTION_PDO :
397:                 $retour = $this->connexion->quote($chaine);
398:                 break;
399:             case self::ABSTRACTION_MYSQL :
400:                 $retour = '"'.mysql_real_escape_string($chaine, $this->connexion).'"';
401:                 break;
402:             case self::ABSTRACTION_MYSQLI :
403:                 $retour = '"'.$this->connexion->real_escape_string($chaine).'"';
404:                 break;
405:             case self::ABSTRACTION_SQLITE3 :
406:                 $retour = $this->connexion->escapeString($chaine);
407:                 break;
408:         }
409:         return $retour;
410:     }
411: 
412:     /**
413:      * @deprecated changement de nom. Deviendra "private" dans la version 0.5. Utiliser à la place : @see proteger
414:      */
415:     public function protegerTableau(Array $tableau) {
416:         foreach ($tableau as $id => $val) {
417:             if (is_array($val)) {
418:                 $tableau[$id] = $this->protegerTableau($val);
419:             } else {
420:                 $tableau[$id] = $this->protegerChaine($val);
421:             }
422:         }
423:         return $tableau;
424:     }
425: 
426:     /**
427:      * Retourne l'identifiant de la dernière ligne insérée, ou la dernière valeur d'une séquence d'objets, dépendamment, dans
428:      * le cas de PDO, du driver utilisé. Les méthodes utilisées pour retourner l'identifiant peuvent avoir des comportements
429:      * différent. Consulter la documentation PHP correspondant à l'abstraction choisie avant de l'utiliser :
430:      * @link(http://fr.php.net/manual/fr/pdo.lastinsertid.php, PDO::lastInsertId([ string $name = NULL ]))
431:      * @link(http://php.net/manual/en/mysqli.insert-id.php, mysqli->insert_id())
432:      * @link(http://fr.php.net/manual/fr/function.mysql-insert-id.php, mysql_insert_id())
433:      * @link(http://fr.php.net/manual/fr/sqlite3.lastinsertrowid.php, SQLite3::lastInsertRowID())
434:      * @param mixed un paramètre éventuel à transmettre (en fonction de l'abstraction de BDD utilisée).
435:      * @return mixed le dernier identifiant de clé primaire ajouté dans la base de données (string ou int).
436:      */
437:     public function recupererIdDernierAjout($parametres = null) {
438:         $this->connecter();
439: 
440:         $retour = null;
441:         switch ($this->abstraction) {
442:             case self::ABSTRACTION_PDO :
443:                 $retour = $this->connexion->lastInsertId($parametres);
444:                 break;
445:             case self::ABSTRACTION_MYSQL :
446:                 $retour = mysql_insert_id($this->connexion);
447:                 break;
448:             case self::ABSTRACTION_MYSQLI :
449:                 $retour = $this->connexion->insert_id();
450:                 break;
451:             case self::ABSTRACTION_SQLITE3 :
452:                 $retour = $this->connexion->lastInsertRowID();
453:                 break;
454:         }
455:         return $retour;
456:     }
457: 
458:     /**
459:      * Destructeur de classe, se contente de fermer explicitement la connexion à la base de donnée.
460:      */
461:     public function __destruct() {
462:         if (isset($this->connexion)) {
463:             switch ($this->abstraction) {
464:                 case self::ABSTRACTION_PDO :
465:                     $this->connexion = null;
466:                     break;
467:                 case self::ABSTRACTION_MYSQL :
468:                     if (isset($this->connexion)) {
469:                         return mysql_close($this->connexion);
470:                     }
471:                     break;
472:                 case self::ABSTRACTION_MYSQLI :
473:                     $this->connexion->close();
474:                     break;
475:                 case self::ABSTRACTION_SQLITE3 :
476:                     $this->connexion->close();
477:                     break;
478:             }
479:         }
480:     }
481: }
482: ?>
483: 
TBFramework - v0.3 API documentation generated by ApiGen 2.8.0