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