La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Bases de données Objet singleton pour la connexion

Présentations similaires


Présentation au sujet: "Bases de données Objet singleton pour la connexion"— Transcription de la présentation:

1 Bases de données Objet singleton pour la connexion
01:08:06 Programmation Web

2 Problème posé Développement d'un site nécessitant une BD :
Connexion en début de chaque page PHP Requête(s) Déconnexion en fin de chaque page PHP Développement objet d'un site avec une BD : Connexions à divers endroits dans les méthodes Requête(s) à divers endroits dans les méthodes Déconnexion en fin de page PHP  Quand doit-on se connecter, se déconnecter ? 01:08:06 Programmation Web

3 Singleton : objet à instance unique Réalisation :
Solution : Singleton Singleton : objet à instance unique Réalisation : 1 attribut statique Singleton 1 point d'accès méthode statique limiter l'accès au constructeur privé / protégé interdire le clonage 01:08:06 Programmation Web

4 Solution : Singleton Adaptation à la connexion BD PDO : myPDO
1 attribut statique mypdo Ressource BD = objet PDO 1 point d'accès Méthode statique get() constructeur privé établit la connexion à la BD destructeur termine la connexion à la BD mise hors service de la méthode __clone throw new Exception("…") ; 01:08:06 Programmation Web

5 Durée de vie de l'objet myPDO
Nature de l'objet membre statique d'une classe : variable globale Construction créé au premier appel de myPDO::get() Destruction variable globale : durée de vie = le script détruit en fin de script Bilan : connexion lors de la première requête déconnexion à la fin du script fonctionnement propre, transparent pour l'utilisateur 01:08:06 Programmation Web

6 Une implémentation <?php
/// Classe permettant de faire une connexion unique et automatique à la BD final class myPDO {     /// Singleton     private static $mypdo = null ;     /// Message de debogage     private static $debug = true ;     /// Data Source Name     private static $dsn   = null ;     /// Utilisateur     private static $user  = null ;     /// Mot de passe     private static $pass  = null ;     /// Connexion à la base     private        $pdo   = null ; 01:08:06 Programmation Web

7 Une implémentation /// Constructeur privé
private function __construct() {     self::msg("Demande construction PDO...") ;     if (       is_null(self::$dsn)             || is_null(self::$user)             || is_null(self::$pass))         throw new Exception("Construction impossible : les paramètres de connexion sont absents") ;     // Etablir la connexion     $this->pdo = new PDO(self::$dsn, self::$user, self::$pass) ;     // Mise en place du mode "Exception" pour les erreurs PDO     $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ;      self::msg("Construction PDO terminée") ; } 01:08:06 Programmation Web

8 Une implémentation /// Destructeur public function __destruct() {
    self::msg("Demande de destruction PDO...") ;     // S'il y a une connexion établie...     if (!is_null($this->pdo))     {         // ... il faut se deconnecter         self::msg("Demande de déconnexion...") ;         $this->pdo   = null ;         self::$mypdo = null ;         self::msg("Deconnexion effectuée") ;     }     self::msg("Destruction PDO terminée") ; } 01:08:06 Programmation Web

9 Une implémentation /// Récupérer le singleton
public static function donneInstance() {     self::msg("Recherche de l'instance...") ;     // Une instance est-elle disponible ?     if (!isset(self::$mypdo))         self::$mypdo = new myPDO() ;     self::msg("Instance trouvée") ;     return self::$mypdo->pdo ; } /// Fixer les paramètres de connexion public static function parametres($_dsn, $_user, $_pass) {     self::$dsn  = $_dsn ;     self::$user = $_user ;     self::$pass = $_pass ; 01:08:06 Programmation Web

10 Une implémentation /// Interdit le clonage du singleton
public function __clone() {     throw new Exception("Clonage de ".__CLASS__." interdit !") ; } 01:08:06 Programmation Web

11 Simple, non ? Utilisation
require_once "connexion.pdo.template.class.php" ; // Paramétrage du singleton myPDO::parametres('oci:dbname=bd11', 'scott', 'tiger') ; // Connexion automatique $pdostat = myPDO::donneInstance()->query( "SELECT * FROM Images") ; while (($ligne = $pdostat->fetch()) !== false) { echo $ligne['id']."<br>\n" ; } // Déconnexion automatique en fin de script Simple, non ? 01:08:06 Programmation Web

12 Raffinement possible : Débogage
Possibilité d'afficher des messages informatifs pour se rendre compte de ce qu'il se passe et dépister les erreurs : connexion… requête… Cadre Web : comment afficher des informations qui ne perturbent pas l'affichage de la page commentaires HTML <!-- … --> doit pouvoir être désactivé  contenus non HTML Implémentation : attribut booléen statique et méthodes statiques 01:08:06 Programmation Web

13 Raffinement possible : Débogage
Problème majeur, les méthodes de requête, préparation, etc sont des méthodes de l'objet PDO et non de myPDO Solution basique la méthode get retourne l'objet myPDO et non PDO l'objet myPDO doit implémenter toutes les méthodes de PDO qui consistent à lancer celles de PDO Solution "avancée" la méthode get() retourne l'objet myPDO et non PDO myPDO doit implémenter __call 01:08:06 Programmation Web

14 Une implémentation v2 /// Récupérer le singleton
public static function donneInstance() {     self::msg("Recherche de l'instance...") ;     // Une instance est-elle disponible ?     if (!isset(self::$mypdo))         self::$mypdo = new myPDO() ;     self::msg("Instance trouvée") ;     // return self::$mypdo->pdo ;     return self::$mypdo ; } 01:08:06 Programmation Web

15 Une implémentation v2 /// Surcharge de toutes les méthodes indisponibles de myPDO pour pouvoir appeler celles de PDO public function __call($methodName/** Nom de la méthode */,                $methodArguments /** Tableau des paramètres */) {     // La méthode appelée fait-elle partie de la classe PDO     if (!method_exists($this->pdo, $methodName))         throw new Exception("PDO::$methodName n'existe pas") ;     // Message de debogage     self::msg("PDO::$methodName (".implode($methodArguments, ", ").")") ;     // Appel de la méthode avec l'objet PDO     $result = call_user_func_array( array($this->pdo, $methodName), $methodArguments) ;     return $result ; } 01:08:06 Programmation Web

16 Une implémentation v2 /// Affichage de messages de contrôle
public static function msg($m /** Le message */) {     if (self::$debug)         Traceur::trace($m) ; } /// Mise en marche du debogage public static function debug_on() {     self::$debug = true ; /// Arrêt du debogage public static function debug_off() {     self::$debug = false ; 01:08:06 Programmation Web

17 Une implémentation v2 - Débogage
/// Singleton permettant de collecter des messages informatifs class Traceur { // Gestion de l'instance unique private static $_instance = null ; /// Objet Traceur // Atttributs de l'objet private        $_messages = array() ; /// Tableau des messages private        $_temps    = null ;    /// Instant de création /// Constructeur privé private function __construct() {     $this->_temps = microtime(true) ; } /// Interdire le clonage private function __clone() {     throw new Exception("Clonage de ".__CLASS__." interdit !") ; 01:08:06 Programmation Web

18 Une implémentation v2 - Débogage
/// Accesseur à l'instance qui sera créée si nécessaire private static function donneInstance() {     if (is_null(self::$_instance)) {         self::$_instance = new self() ;     }     return self::$_instance ; } /// Méthode statique de collecte de messages public static function trace($msg) {     $instance = self::donneInstance() ;     $instance->messages[] = $instance->duree() . " secondes : "  .$msg ; 01:08:06 Programmation Web

19 Une implémentation v2 - Débogage
/// Calcul du temps écoulé depuis la création du traceur private function duree() {     return number_format(microtime(true) - $this->_temps, 4) ; } /// Méthode statique d'affichage des messages collectés public static function affiche($avant = "<!--", $apres = "-->") {     $messages =  self::donneInstance()->messages ;     $traces = null ;     if (count($messages)) {         $traces .= "{$avant}\n" ;         foreach ($messages as $m) {             $traces .= "{$m}\n" ;         }         $traces .= "{$apres}\n" ;     }     return $traces ; } } 01:08:06 Programmation Web

20 Une implémentation v2 - Débogage
/// Calcul du temps écoulé depuis la création du traceur private function duree() {     return number_format(microtime(true) - $this->_temps, 4) ; } /// Méthode statique d'affichage des messages collectés public static function affiche($avant = "<!--", $apres = "-->") {     $messages =  self::donneInstance()->messages ;     $traces = null ;     if (count($messages)) {         $traces .= "{$avant}\n" ;         foreach ($messages as $m) {             $traces .= "{$m}\n" ;         }         $traces .= "{$apres}\n" ;     }     return $traces ; } } 01:08:06 Programmation Web

21 Une implémentation v2 - Débogage
Utilisation de la classe Traceur dans la classe myPDO : affichage des traces à la destruction /// Destructeur de myPDO public function __destruct() {     self::msg("Demande de destruction PDO...") ;     // S'il y a une connexion établie...     if (!is_null($this->pdo))     {         // ... il faut se deconnecter         self::msg("Demande de déconnexion...") ;         $this->pdo   = null ;         self::$mypdo = null ;         self::msg("Deconnexion effectuée") ;     }     self::msg("Destruction PDO terminée") ;    echo Traceur::affiche() ; } 01:08:06 Programmation Web

22 Raffinement possible : Débogage (suite)
La solution est partielle : Les messages d'information concernent uniquement les méthodes de PDO Une requête préparée retourne un objet PDOStatement qui effectuera les méthodes bindValue, execute, fetch, … Comment tracer TOUTES les actions effectuées sur la base de données ?  Implémenter un objet myPDOStatement 01:08:06 Programmation Web

23 Une implémentation V3 /// Encapsulation de PDOStatement
final class myPDOStatement {     /// L'objet PDOStatement     private $pdoStatement ;     /// Constructeur     public function __construct($_pdoStatement /** L'objet PDOStatement */) {         myPDO::msg("Construction PDOStatement") ;         $this->pdoStatement = $_pdoStatement ;     }     /// Destructeur     public function __destruct() {         myPDO::msg("Destruction PDOStatement") ;         $this->pdoStatement = null ; 01:08:06 Programmation Web

24 Une implémentation V3 /// Surcharge de toutes les méthodes indisponibles de myPDOStatement pour pouvoir appeler celles de PDOStatement public function __call($methodName/** Nom de la méthode */,                $methodArguments /** Tableau des paramètres */) {     // La méthode appelée fait-elle partie de la classe PDOStatement     if (!method_exists($this->pdoStatement, $methodName))         throw new Exception("PDOStatement::$methodName n'existe pas") ;     // Message de debogage     myPDO::msg("PDOStatement::".$methodName. " (".var_export($methodArguments, true).")") ;     // Appel de la méthode avec l'objet PDOStatement     return call_user_func_array( array($this->pdoStatement, $methodName), $methodArguments) ; } 01:08:06 Programmation Web

25 Une implémentation V3.1 Utilisation de myPDOStatement au lieu de PDOStatement ? public function __call($methodName/** Nom de la méthode */,                $methodArguments /** Tableau des paramètres */) {     // La méthode appelée fait-elle partie de la classe PDO     if (!method_exists($this->pdo, $methodName))         throw new Exception("PDO::$methodName n'existe pas") ;     // Message de debogage     self::msg("PDO::$methodName (".implode($methodArguments, ", ").")") ;     // Appel de la méthode avec l'objet PDO     $result = call_user_func_array( array($this->pdo, $methodName), $methodArguments) ;     return $result ; } // Selon le nom de la méthode switch ($methodName) { // Cas 'prepare' ou 'query' => fetchNamed case "prepare" : case "query" : $result->setFetchMode(PDO::FETCH_NAMED) ; // Retourne un objet myPDOStatement return new myPDOStatement($result) ; // Dans tous les autres cas default : // Retourne le résultat return $result ; } 01:08:06 Programmation Web

26 Aide au débogage, suite (et fin ?)
error_reporting(E_ALL) ; /** Mise en place d'une capture des exceptions non attrapées */ function exceptionHandler($exception /** L'Exception non attrapée */) { echo "<pre>\n" ; echo $exception->getMessage()."\n" ; echo "Trace d'execution :\n" ; echo $exception->getTraceAsString() ; echo "</pre>\n" ; } set_exception_handler('exceptionHandler') ; 01:08:06 Programmation Web


Télécharger ppt "Bases de données Objet singleton pour la connexion"

Présentations similaires


Annonces Google