Classes "extendue" de PDO

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Classes "extendue" de PDO

par jojolapine » 01 déc. 2006, 19:32

Bon j'ouvre un nouveau topic... :cry: => http://www.phpfrance.com/forums/voir_sujet-24916.php

par Ajoloca » 01 déc. 2006, 15:30

Bonjour,

Essaie de passer la même requête sans utiliser les class étendues (My*), en utilisant PDO et PDOStatement (les "originaux") pour voir ce que ça donne.

Si ça marche, je reviserais les class mais ça marche parfaitement chez moi.

Dans le cas contraire, ouvre un nouveau topic et on essyera de déterminer la cause

par jojolapine » 01 déc. 2006, 12:54

merci merci pour les efforts que tu faits mais regarde le résultat chez moi: http://puffins.fr/concertation/essaiPDO4.php
ça ne fait pas le tri sur le where...

par Ajoloca » 01 déc. 2006, 05:19

Bonsoir,

Voilà QQ chose qui me plait bien mieux, ça respecte réellement la philosophie Objet et celle de PDO.
Les class ne sont pas totalement terminées (commentaires, amélliorations, etc...)
La façon d'écrire la fonction n'est pas à prendre en exemple (ou si tu tiens à la prendre en exemple, c'est ceux qu'il ne faut jamais faire - global, etc..)
mais pour le test on peux le pardonner.
<?php

class MyPDO extends PDO{
	const ALL_QRY = 0;
	const DIRECT_QRY = 1;
	const PREP_QRY = 2;
	/*
   */
	static $preparedQry = 0;
	static $directQry = 0;
	/*
   */
	public function __construct($dsn, $user, $pass){
   	try{
			parent::__construct($dsn, $user, $pass);
			// Activation du mode de gestion des erreurs par levée d'exception
			$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			// On précise à PDO la class qui doit gérer les Statements
			$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement', array($this)));
		}
		// Une exception de type PDO à été levée
		catch(PDOException $e){
			// On ne traite pas l'execption, on la transmet
			throw $e;
   	}
   }
   /*
   */
   public function query($params){
   	try{
   		self::$directQry++;
   		parent::query($params);
   	}
   	catch(PDOException $e){
   		throw $e;
   	}
   }
   /*
   */
   public function exec($params){
   	try{
   		self::$directQry++;
   		parent::exec($params);
   	}
   	catch(PDOException $e){
   		throw $e;
   	}
   }
   /*
   */
   public function addPreparedQry($objStatement){
   	// Permet de controler que la méthode à été appellée à partir de la class MyPDOStatement
   	// Evite de faire incrémenter les requêtes préparées d'un autre endroit
   	if(get_class($objStatement) === false || get_class($objStatement) != 'MyPDOStatement'){
   		throw new PDOException ('Appel invalide &agrave; la m&eacute;thode <b>' . __METHOD__ . '</b>');
   	}
   	self::$preparedQry++;
   }
   /*
   */
   public function getQryNumber($type = MyPDO::ALL_QRY){
   	switch($type){
	   	case MyPDO::DIRECT_QRY :
   			return(self::$directQry);
   		case MyPDO::PREP_QRY :
	   		return(self::$preparedQry);
	   	case MyPDO::ALL_QRY :
	   	default :
	   	return(self::$preparedQry + self::$directQry);
   	}
   }
}
/*
*
*
*
*/
class MyPDOStatement extends PDOStatement{
   public $stmt;
   
   protected function __construct($stmt){
       $this->stmt = $stmt;
       $this->setFetchMode(PDO::FETCH_OBJ);
   }
   /*
   */
   public function execute($params = null){
   	$this->stmt->addPreparedQry($this);
   	parent::execute($params);
   }
}
/*
*
*
*
*/
function executionRequetePreparee(){
	global $stmt, $id;
	try{
		echo '<h3>Execute() ID <= ' . $id . '</h3>';
		$stmt->execute();
		echo '<table><tr><th>ID</th><th>Auteur</th><th>Titre</th></tr>';
		while($row = $stmt->fetch(PDO::FETCH_OBJ)){
			echo '<tr>';
			echo '<td>' . $row->id . '</td><td>' . utf8_decode($row->Auteur) . '</td><td>' . utf8_decode($row->Titre) . '</td>';
			echo '</tr>';
		}
		echo '</table>';
	}
	catch (PDOException $e){
		die ('<h2>ERR execute() :</h2>' . $e->getMessage());
	}	
}
/*
*
*
*
*/
$dsn = 'mysql:host=localhost; dbname=test';
$user = '****';
$passWd = '****';
try{
	$cnx = new MyPDO($dsn, $user, $passWd);
}
catch(PDOExecption $ePDO){
	die ('<h2>ERR de Connexion :</h2>' . $ePDO->getMessage());
}
echo '<h2>Connexion OK !</h2>';
try{
	$stmt = $cnx->prepare('SELECT id, Auteur, Titre  FROM livres WHERE id <= :id');
}
catch (PDOException $e){
	die ('<h2>ERR de pr&eacute;paration de Qry :</h2>' . $ePDO->getMessage());
}
echo '<h2>Prepare() OK !</h2>';
$stmt->bindParam(':id', $id);
$id = 20;
executionRequetePreparee();
$id = 30;
executionRequetePreparee();
$id = 40;
executionRequetePreparee();
echo '<h2>Requ&ecirc;tes pr&eacute;par&eacute;es = ' . $cnx->getQryNumber(MyPDO::PREP_QRY) . '</h2>';
$cnx = null;
?>

par rami » 29 nov. 2006, 14:36

Effectivement, je pensais que le mode par défaut de PDO pour la gestion des erreurs était par exception, mais ce n'est pas le cas.
Il suffit via setAttribute de passer PDO::ATTR_ERRMODE à PDO::ERRMODE_EXCEPTION, ce qui fait que PDO lance une exception qd il rencontre un erreur, ce qui est beaucoup plus objet.

par jojolapine » 29 nov. 2006, 03:18

<?php
/**
 * Extension de la class PDO
 *
 * Le but de cette class est de comptabiliser
 * - le nombre de requêtes retournant des données
 *
 * @package 
 * @access public
 * @author Ajoloca
 * @copyright 
 * @version 1.0
 */
class MyPDO extends PDO{
    /**
     * Variable contenant le nombre requêtes
     * 
     * @staticvar numeric
     */
    static $qriesCount = 0;
    static $qryPrepared = 0;
    static $directQry = 0;
    public $stmt = null;
    /**
     * Méthode constructeur
     * 
     * Fait appel à la class parente (PDO)
     *
     * @access public
     * @param string $dsn chaine de type DSN (Data Server Name)
     * @param string $user utilisateur
     * @param string $pass mot de passe pour l'utilisateur
     * @exception PDOException
     * @see PDOException
     */
    public function __construct($dsn, $user, $pass){
        // Appel au constructeur parent
        try{
            parent::__construct($dsn, $user, $pass);
            // Activation du mode de gestion des erreurs par levée d'exception
            $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        // Une exception de type PDO à été levée
        catch(PDOException $e){
            // On ne traite pas l'execption, on la transmet
            throw $e;
       }
   }
   /**
     * Méthode de gestion des requêtes qui retournent des données
     * 
     * Utilise (redéfinit) la méthode prente du même nom
     * Incrémente le nombre de requêtes
     *
     * @access public
     * @param string $qry requête à exécuter
     *
     */
   public function query($qry){
       try{
           $this->query($qry);
           self::$directQry++;
           return($tmp);
       }
       catch(Exception $eQry){
           throw $eQry;
       }
   }
   public function prepare($qry){
       try{
           $this->stmt = parent::prepare($qry);
           echo '<h4>Je pr&eacute;repare la requ&ecirc;te<br />' . $qry . '</h4>';
           return ($this->stmt);
       }
       catch(PDOEsception $e){
           throw $e;
       }
   }
   public function execute($params = null){
       try{
           self::$qryPrepared++;
           return ($this->stmt->execute($params));
       }
       catch(PDOEsception $e){
           throw $e;
       }
   }
   public function getQueryCount(){
           return (self::$qriesCount);
   }
    public function getQueryPrepared(){
           return (self::$qryPrepared);
   }
}

/**
 *
 *
 *
 */ 
$dsn = 'mysql:host=****; dbname=concertation';
$user = '****';
$passWd = '****';
try{
    $cnx = new MyPDO($dsn, $user, $passWd);
}
catch(PDOExecption $ePDO){
    die ('ERR de Connexion :<br />' . $ePDO->getMessage());
}
echo '<h3>Connexion OK</h3>';
echo 'Requ&ecirc;tes : ' . $cnx->getQueryCount() . '<br />';
// Construction de la requête
$qrySel = 'SELECT id, Auteur, Titre FROM livres WHERE id <= :id';
try{
    // Préparation de la requête
     $stmt = $cnx->prepare($qrySel);
}
catch(PDOException $e){
    die($e->getMessage());
}
// Association des àramètres nommés à une variable
try{
    $stmt->bindParam(':id', $i);
}
catch(Exception $e){
    echo '<h3>Dans execute</h3>';
    die($e->getMessage());
}
// Exécution de la requête
try{
        $i = 20;
        echo '<h2>Premier execute id <= ' . $i . '</h2>';
        $cnx->execute();
        while($row = $stmt->fetch(PDO::FETCH_OBJ))
            echo 'id = ' . $row->id . ' Auteur : ' . utf8_decode($row->Auteur) . ' Titre : ' . utf8_decode($row->Titre) . '<br />';
        $i = 30;
        echo '<h2>nouvel execute id <= ' . $i . '</h2>';
        
        $cnx->execute();
        while($row = $stmt->fetch(PDO::FETCH_OBJ))
            echo 'id = ' . $row->id . ' Auteur : ' . utf8_decode($row->Auteur) . ' Titre : ' . utf8_decode($row->Titre) . '<br />';
        echo '<h2>Pr&eacute;par&eacute;es = ' . $cnx->getQueryPrepared() . '</h2>';
}
catch(Exception $e){
    die($e->getMessage());
}
?>
Voilà un simple copier/coller, j'ai juste changer $user $pass, ...
rien touché d'autre!
bon sur ce je craque, je vais me coucher
Bonne nuit à toi et t'arrache pas les cheveux ce soir, attend demain qu'on se les arraches à l'unisson! :wink:
merci encore

par Ajoloca » 29 nov. 2006, 03:15

Poste ton code, c'est pas possible!

par jojolapine » 29 nov. 2006, 03:12

bon ben il y a visiblemnt une différence de config, car voici ce que j'ai en changeant seulement le serveur et la bdd: http://puffins.fr/concertation/essaiPDO4.php
comme tu le vois, ça ne fait pas la clause where correctement

par Ajoloca » 29 nov. 2006, 02:49

je t'ai mis en téléchargement le fichier livres.sql.zip (comme je ne sais quel système tu utilies je l'ai compressé en zip - utilisable sous Win... et Linux)
pour le télécharger ICI

par jojolapine » 29 nov. 2006, 02:37

ben je comprend plus rien, pourquoi ça marche pas chez moi? y aurait t'il une directive php ou quoi ? qui ferai que ? (phpinfo de chez moi
Sinon ça te dérengerai de me faire un export (en partie de ta bdd de test ? pour voir si c'est ma bdd ou ma requête?)

par Ajoloca » 29 nov. 2006, 02:24

Avec exactement le cose que je t'ai donné
regarde ce que ça donne chez moi

Comme il n'y-a pas d'entêtes HTML tu doit mettre ton navigateur en affichage UTF8 sinon tu auras des caractères biz...

par jojolapine » 29 nov. 2006, 02:16

Tout d'abord MERCI (j'espère pas d'avoir prit ta soirée... :oops: )
Ensuite, pour ce qui est de la classe, après les premiers tests, il apparait que je n'arrive pas à exécuter la requête préparée, en effet, si je laisse :id, ça ne retourne rien, comme s'il n'y avait pas de résultats, si je met en dur l'id, ça fonctionne, exemple:
http://puffins.fr/concertation/essaiPDO3.php

par Ajoloca » 29 nov. 2006, 01:44

Bon,
J'ai QQ chose qui tourne mais ne conviens pas trop.

Elle "déforme" la philosophie de PDO, on doit faire l'execute à partir de l'objet PDO au lieu de la faire à partir PDOStatment.

Je vais réfléchir à la chose, je te donne ce que j'ai fait pour l'instant
@Cyrano, je sais, les commentaires. Je te promets qu'il y seront une fois la (les) classe(s) finalisée(s)
<?php
/**
 * Extension de la class PDO
 *
 * Le but de cette class est de comptabiliser
 * - le nombre de requêtes retournant des données
 *
 * @package 
 * @access public
 * @author Ajoloca
 * @copyright 
 * @version 1.0
 */
class MyPDO extends PDO{
	/**
	 * Variable contenant le nombre requêtes
	 * 
	 * @staticvar numeric
	 */
	static $qriesCount = 0;
	static $qryPrepared = 0;
	static $directQry = 0;
	public $stmt = null;
	/**
	 * Méthode constructeur
	 * 
	 * Fait appel à la class parente (PDO)
	 *
	 * @access public
	 * @param string $dsn chaine de type DSN (Data Server Name)
	 * @param string $user utilisateur
	 * @param string $pass mot de passe pour l'utilisateur
	 * @exception PDOException
	 * @see PDOException
	 */
	public function __construct($dsn, $user, $pass){
		// Appel au constructeur parent
		try{
			parent::__construct($dsn, $user, $pass);
			// Activation du mode de gestion des erreurs par levée d'exception
			$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		}
		// Une exception de type PDO à été levée
		catch(PDOException $e){
			// On ne traite pas l'execption, on la transmet
			throw $e;
   	}
   }
   /**
	 * Méthode de gestion des requêtes qui retournent des données
	 * 
	 * Utilise (redéfinit) la méthode prente du même nom
	 * Incrémente le nombre de requêtes
	 *
	 * @access public
	 * @param string $qry requête à exécuter
	 *
	 */
   public function query($qry){
   	try{
   		$this->query($qry);
   		self::$directQry++;
   		return($tmp);
   	}
   	catch(Exception $eQry){
   		throw $eQry;
   	}
   }
   public function prepare($qry){
   	try{
   		$this->stmt = parent::prepare($qry);
   		echo '<h4>Je pr&eacute;repare la requ&ecirc;te<br />' . $qry . '</h4>';
   		return ($this->stmt);
   	}
   	catch(PDOEsception $e){
   		throw $e;
   	}
   }
   public function execute($params = null){
   	try{
   		self::$qryPrepared++;
   		return ($this->stmt->execute($params));
   	}
   	catch(PDOEsception $e){
   		throw $e;
   	}
   }
   public function getQueryCount(){
   		return (self::$qriesCount);
   }
	public function getQueryPrepared(){
   		return (self::$qryPrepared);
   }
}

/**
 *
 *
 *
 */ 
$dsn = 'mysql:host=localhost; dbname=test';
$user = '******';
$passWd = '########';
try{
	$cnx = new MyPDO($dsn, $user, $passWd);
}
catch(PDOExecption $ePDO){
	die ('ERR de Connexion :<br />' . $ePDO->getMessage());
}
echo '<h3>Connexion OK</h3>';
echo 'Requ&ecirc;tes : ' . $cnx->getQueryCount() . '<br />';
// Construction de la requête
$qrySel = 'SELECT id, Auteur, Titre FROM livres WHERE id <= :id';
try{
	// Préparation de la requête
	 $stmt = $cnx->prepare($qrySel);
}
catch(PDOException $e){
	die($e->getMessage());
}
// Association des àramètres nommés à une variable
try{
	$stmt->bindParam(':id', $i);
}
catch(Exception $e){
	echo '<h3>Dans execute</h3>';
	die($e->getMessage());
}
// Exécution de la requête
try{
		$i = 20;
		echo '<h2>Premier execute id <= ' . $i . '</h2>';
		$cnx->execute();
		while($row = $stmt->fetch(PDO::FETCH_OBJ))
			echo 'id = ' . $row->id . ' Auteur : ' . utf8_decode($row->Auteur) . ' Titre : ' . utf8_decode($row->Titre) . '<br />';
		$i = 30;
		echo '<h2>nouvel execute id <= ' . $i . '</h2>';
		
		$cnx->execute();
		while($row = $stmt->fetch(PDO::FETCH_OBJ))
			echo 'id = ' . $row->id . ' Auteur : ' . utf8_decode($row->Auteur) . ' Titre : ' . utf8_decode($row->Titre) . '<br />';
		echo '<h2>Pr&eacute;par&eacute;es = ' . $cnx->getQueryPrepared() . '</h2>';
}
catch(Exception $e){
	die($e->getMessage());
}
?>
Comme tu le vois il-y-a des affichages totalement inutiles, mais tu est développeur...

par Ajoloca » 28 nov. 2006, 22:31

Oufff....
Tu me rassures !
Je dinne et regarde le PB de execute().

par jojolapine » 28 nov. 2006, 22:26

Dsl pour toi rami, mais en effet si l'on ne fait pas de try catch dans la classe, les erreurs ne sont pas transmises...
Un point pour Ajoloca