Classes "extendue" de PDO

ViPHP
ViPHP | 1961 Messages

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...
Modifié en dernier par Ajoloca le 29 nov. 2006, 02:25, modifié 1 fois.
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

ViPHP
ViPHP | 3607 Messages

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

ViPHP
ViPHP | 1961 Messages

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...
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

ViPHP
ViPHP | 3607 Messages

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?)

ViPHP
ViPHP | 1961 Messages

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
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

ViPHP
ViPHP | 3607 Messages

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

ViPHP
ViPHP | 1961 Messages

29 nov. 2006, 03:15

Poste ton code, c'est pas possible!
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

ViPHP
ViPHP | 3607 Messages

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

Mammouth du PHP | 983 Messages

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.

ViPHP
ViPHP | 1961 Messages

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;
?>
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

ViPHP
ViPHP | 3607 Messages

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...

ViPHP
ViPHP | 1961 Messages

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
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

ViPHP
ViPHP | 3607 Messages

01 déc. 2006, 19:32

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