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

Jérôme CUTRONA 11:43:39 Programmation Web 2012-2013 1 Bases de données Objet singleton pour la connexion.

Présentations similaires


Présentation au sujet: "Jérôme CUTRONA 11:43:39 Programmation Web 2012-2013 1 Bases de données Objet singleton pour la connexion."— Transcription de la présentation:

1 Jérôme CUTRONA 11:43:39 Programmation Web Bases de données Objet singleton pour la connexion

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

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

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

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

6 611:43:39 Programmation Web Une implémentation

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

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

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

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

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

12 1211:43:39 Programmation Web 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 : Possibilité d'afficher des messages informatifs pour se rendre compte de ce qu'il se passe et dépister les erreurs : connexion… connexion… requête… requête… Cadre Web : Cadre Web : comment afficher des informations qui ne perturbent pas l'affichage de la page comment afficher des informations qui ne perturbent pas l'affichage de la page commentaires HTML commentaires HTML doit pouvoir être désactivé contenus non HTML doit pouvoir être désactivé contenus non HTML Implémentation : Implémentation : attribut booléen statique et méthodes statiques attribut booléen statique et méthodes statiques

13 1311:43:39 Programmation Web 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 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 Solution basique la méthode get retourne l'objet myPDO et non PDO 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 l'objet myPDO doit implémenter toutes les méthodes de PDO qui consistent à lancer celles de PDO Solution "avancée" Solution "avancée" la méthode get() retourne l'objet myPDO et non PDO la méthode get() retourne l'objet myPDO et non PDO myPDO doit implémenter __call myPDO doit implémenter __call

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

15 1511:43:39 Programmation Web 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 */ ) { $methodArguments /** Tableau des paramètres */ ) { // La méthode appelée fait-elle partie de la classe PDO // La méthode appelée fait-elle partie de la classe PDO if (!method_exists($this->pdo, $methodName)) if (!method_exists($this->pdo, $methodName)) throw new Exception("PDO::$methodName n'exis te pas") ; throw new Exception("PDO::$methodName n'exis te pas") ; // Message de debogage // Message de debogage self::msg("PDO::$methodName (".implode($methodAr guments, ", ").")") ; self::msg("PDO::$methodName (".implode($methodAr guments, ", ").")") ; // Appel de la méthode avec l'objet PDO // Appel de la méthode avec l'objet PDO $result = call_user_func_array( $result = call_user_func_array( array($this->pdo, $methodName), $methodArguments) ; return $result ; return $result ;}

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

17 1711:43:39 Programmation Web 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) ; $this->_temps = microtime(true) ;} /// Interdire le clonage private function __clone() { throw new Exception("Clonage de ".__CLASS__." interdit !") ; throw new Exception("Clonage de ".__CLASS__." interdit !") ;}

18 1811:43:39 Programmation Web 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)) { if (is_null(self::$_instance)) { self::$_instance = new self() ; self::$_instance = new self() ; } return self::$_instance ; return self::$_instance ;} /// Méthode statique de collecte de messages public static function trace($msg) { $instance = self::donneInstance() ; $instance = self::donneInstance() ; $instance->messages[] = $instance->duree(). " secondes : ".$msg ; $instance->messages[] = $instance->duree(). " secondes : ".$msg ;}

19 1911:43:39 Programmation Web 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) ; return number_format(microtime(true) - $this->_temps, 4) ;} /// Méthode statique d'affichage des messages collectés public static function affiche($avant = " ") { $messages = self::donneInstance()->messages ; $messages = self::donneInstance()->messages ; $traces = null ; $traces = null ; if (count($messages)) { if (count($messages)) { $traces.= "{$avant}\n" ; $traces.= "{$avant}\n" ; foreach ($messages as $m) { foreach ($messages as $m) { $traces.= "{$m}\n" ; $traces.= "{$m}\n" ; } $traces.= "{$apres}\n" ; $traces.= "{$apres}\n" ; } return $traces ; return $traces ; } }

20 2011:43:39 Programmation Web 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) ; return number_format(microtime(true) - $this->_temps, 4) ;} /// Méthode statique d'affichage des messages collectés public static function affiche($avant = " ") { $messages = self::donneInstance()->messages ; $messages = self::donneInstance()->messages ; $traces = null ; $traces = null ; if (count($messages)) { if (count($messages)) { $traces.= "{$avant}\n" ; $traces.= "{$avant}\n" ; foreach ($messages as $m) { foreach ($messages as $m) { $traces.= "{$m}\n" ; $traces.= "{$m}\n" ; } $traces.= "{$apres}\n" ; $traces.= "{$apres}\n" ; } return $traces ; return $traces ; } }

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

22 2211:43:39 Programmation Web Raffinement possible : Débogage (suite) La solution est partielle : La solution est partielle : Les messages d'information concernent uniquement les méthodes de PDO 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, … 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 ? Comment tracer TOUTES les actions effectuées sur la base de données ? Implémenter un objet myPDOStatement Implémenter un objet myPDOStatement

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

24 2411:43:39 Programmation Web 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 */ ) { $methodArguments /** Tableau des paramètres */ ) { // La méthode appelée fait-elle partie de la classe PDOStatement // La méthode appelée fait-elle partie de la classe PDOStatement if (!method_exists($this->pdoStatement, $methodName)) if (!method_exists($this->pdoStatement, $methodName)) throw new Exception("PDOStatement::$methodName n'e xiste pas") ; throw new Exception("PDOStatement::$methodName n'e xiste pas") ; // Message de debogage // Message de debogage myPDO::msg("PDOStatement::".$methodName. myPDO::msg("PDOStatement::".$methodName. " (".var_export($methodArguments, true).")") ; " (".var_export($methodArguments, true).")") ; // Appel de la méthode avec l'objet PDOStatement // Appel de la méthode avec l'objet PDOStatement return call_user_func_array( return call_user_func_array( array($this->pdoStatement, $methodName), array($this->pdoStatement, $methodName), $methodArguments) ; $methodArguments) ;}

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

26 2611:43:39 Programmation Web 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 */) { /** L'Exception non attrapée */) { echo " \n" ; echo " \n" ; echo $exception->getMessage()."\n" ; echo $exception->getMessage()."\n" ; echo "Trace d'execution :\n" ; echo "Trace d'execution :\n" ; echo $exception->getTraceAsString() ; echo $exception->getTraceAsString() ; echo " \n" ; echo " \n" ;} set_exception_handler('exceptionHandler') ;


Télécharger ppt "Jérôme CUTRONA 11:43:39 Programmation Web 2012-2013 1 Bases de données Objet singleton pour la connexion."

Présentations similaires


Annonces Google