Classes "extendue" de PDO

ViPHP
ViPHP | 1961 Messages

25 nov. 2006, 20:46

Re,
Tu as trouvé ton erreur ou tu as laissé tamber?
Je penche pour la première car elle est évidente (l'erreur).
Si c'est la seconde, c'est dommage si près du but.
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

26 nov. 2006, 01:46

AHAHAHAHAHA, je crois que j'ai trouvé!!!!!
j'avais oublié le return parent::query(...)
c'est ça ? (en tout cas ça fonctionne!!!)
Bon après je ne comprend toujours pas ce qu'ils disent dans la doc, concernant les paramètres...
sinon voici le code de la méthode query:
public function query($q)
    {
      try{
        self::$nbrQuery+=1;
        return parent::query($q);
      }catch(PDOException $e){
        throw $e;
      }  
    }
Sinon une dernière (c'est pas sûr hein... :roll: ) question... pour la gestion des erreurs, est-ce que je ferai pas mieux pour la version finale, de définir une variable private $error;
et si elle a un contenu, je l'affiche dans le destructeur ?

voilivoilou
(en tout cas merci de t'acharner Ajoloca, ça m'a beaucoup aidé :wink:

ViPHP
ViPHP | 1961 Messages

26 nov. 2006, 02:01

Re,
Hereu de te voir de retour vainqueur!
@Cyrano Non, :axe: pas pour les commentaires, j'ai pas eu le temps

Comme je ne sais pas exactement quel est ton PB sur les params, je te donne un exemple "bidon" mais fonctionnel (sans commentaires, je sais...)
De cette maniere tu pouras voir de plus près et affiner tes questions
<?php
class MyPDO extends PDO{
	static $qriesCount = 0;
	public function __construct($dsn, $user, $pass){
		try{
			parent::__construct($dsn, $user, $pass);
		}
		catch(PDOException $e){
			throw $e;
   	}
   }
   public function query($qry){
   	try{
   		self::$qriesCount++;
   		return(parent::query($qry));
   	}
   	catch(Exception $eQry){
   		throw $eQry;
   	}
   }
   public function getQueryCount(){
   	return (self::$qriesCount);
   }
}
$dsn = 'mysql:host=localhost; dbname=test';
$user = 'xxx';
$passWd = 'yyy';
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 />';
$qrySel = 'SELECT COUNT(*) nombre FROM `livres`';
for($i = 0; $i < 3; $i++){
	$resQrySel = $cnx->query($qrySel);
	if($i == 0){
		$nbrRangs = $resQrySel->fetchAll(PDO::FETCH_OBJ);
		echo 'Valeur trouv&eacute;e = ' . $nbrRangs[0]->nombre. '<br />';
	}
	echo 'Requ&ecirc;tes : ' . $cnx->getQueryCount() . '<br />';
}
?>
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

26 nov. 2006, 02:18

on a gagné on a gagné!!!
Bon sinon plus sèrieusement, je ais peu-être paraitre pénible, mais je trouve
ça:
try{
    $cnx = new MyPDO($dsn, $user, $passWd);
}
catch(PDOExecption $ePDO){
    die ('ERR de Connexion :<br />' . $ePDO->getMessage());
} 
un peu lourd à réécrire dans le code, il n'y aurai pas un moyen de gérer ça en interne dans la classe un truc comme ça (sans commentaires... pardon cyrano [-o< )
public function query($q)
    {
      try{
        self::$nbrQuery+=1;
        return parent::query($q);
      }catch(PDOException $e){
        self::$error=$e->getMessage();
      }  
    }
bon c'est peut-être du grand n'importe quoi le code que j'ai mis mais c'est pour montrer la façon dont je verrai les choses ...
tu vois à peu près ?
SInon je ne comprend pas une chose, pourquoi dans ta méthode __construct, tu faits un try catch, et tu en refaits un lors de l'appel de la méthode, dans le code... pourquoi c'est deux occurrences?

ViPHP
ViPHP | 1961 Messages

26 nov. 2006, 02:47

Ça peux sembler lourd, c'est comme pour certains faire un test sur le retour de mysql_*.
Ils sont surs que tout se passera comme dans leur tête (c'est à dire bien)
un peu lourd à réécrire dans le code, il n'y aurai pas un moyen de gérer ça en interne dans la classe un truc comme ça (sans commentaires... pardon cyrano Pray )
PHP:
public function query($q)
{
try{
self::$nbrQuery+=1;
return parent::query($q);
}catch(PDOException $e){
self::$error=$e->getMessage();
}
}
Que retournerais-tu en cas d'erreur ?
Qui te dis que ce qui m'intéresse c'est le message ?
Qui te dis que dans ma programmation tout va bien si et seulement si elle provoque une Exception de la class X.

Dans le constructeur, je teste si "l'instentiation" c'est bien passée, sinon je ne fais que transmettre l'execption, c'est pas le rôle du constructeur de l'interpréter, c'est à celui qui l'appele.

A la création de l'objet (je suis le demandeur) je teste si une exception de la classe PDOException à été levée.
Mon constructeur peux très bien lever une exception d'une autre class.

Un autre exemple:
J'écris un PGM qui si la class PDO existe va s'enservir, sinon je vais utiliser mysql "clasique".
Avec ta façon de coder, je fais comment?
L'exception PDO a pu être levée, mais pas parce que la class n'existe pas, mais que le mot de passe est invalide, (à ce sujet, la class que je t'ai fournie n'est pas complète, elle devrait encore "catcher" Exception) comment je le sais si j'ai que message, je crée des regx pour analyser le message en fonction de tous les texte possibles (que par ailleurs je ne connais pas) ?
rien qu'avec ça mon code est bien plus lourd, difficile à comprendre, etc...
J'oubliais, et la réutilisation "universalité" dans tout ça, elle est où?
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

26 nov. 2006, 03:03

Vu! pour la "génricité" (de générique) du code...
j'ai rechanger la gestion des erreurs, par contre, si je fait un erreur sur ma requête, et que je met ma methode query dans un while ça me génère une erreur php invalid argument et non pas une erreur PDO...

ViPHP
ViPHP | 1961 Messages

26 nov. 2006, 03:05

Je vois pas bien, montre un exemple.
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

26 nov. 2006, 03:11

et bien si je fait quelque chose comme ça:
try {
   $dbh = new SQL('mysql:host=xxx;dbname=xxx', $user, $pass);
   foreach ($dbh->query('un requete fausse') as $row) {
     print_r($row);
   }
   $dbh = null;
} catch (PDOException $e) {
print "Erreur ! : " . $e->getMessage() . "<br/>";
die();
}
l'erreur retournée est :
Warning: Invalid argument supplied for foreach() in essaiPDO.php on line 100
alors que j'aurai aimé un
You have an error on your SQL syntaxe, check the manuel...
tu comprends mieu?

Invité
Invité n'ayant pas de compte PHPfrance

26 nov. 2006, 03:27

foreach itère, que retourne $dbh->query ?

ViPHP
ViPHP | 1961 Messages

26 nov. 2006, 03:33

Si tu regardes l'exemple que je t'ai donné il te manque une étape (s'il avait commenté dirait Cyrano).

En MySQL "classique" tu procédais par étapes
1 - Connexion, sélection d'une base
2 - Envoie de la requête
3 - fetch sur la ressource
4 - boucle sur le résultat du fetch

Les étapes ne changent pas.
Regarde bien ton code.
Modifié en dernier par Ajoloca le 26 nov. 2006, 03:40, 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 | 1961 Messages

26 nov. 2006, 03:35

Désolé, j'avais posté sans voir ton message.
foreach itère, que retourne $dbh->query ?
$dbh->query() Retourne une ressource

EDIT :
Et là je m'apperçois que c'est QQ d'autre. Je crois que je ne vois plus clair, ça doit être l'heure :oops:
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

26 nov. 2006, 11:49

c'est vrai que dans la doc il notes:
Une fonctionnalité intéressante de PDO::query() est qu'il vous permet d'itérer à travers un jeu de résultats retourné par une requête SELECT exécutée avec succès.
donc c'est normal que ça ne marche pas...
par contre j'ai essayé en séparant bien les différentes étapes que tu m'as rappelé:
$user='xxx';
$pass='xxx';
try{
  $connec=new SQL('mysql:host=xxx;dbname=xxx', $user, $pass);
} catch (PDOException $e) {
  die("Erreur de connection: <br />".$e->getMessage());
}

$sql='SELECT * FROM `matable`';
try{
  $resQrySel = $connec->query($sql);
} catch (PDOException $e){
  die("Erreur d'éxécution de la requête:<br />".$sql."<br />Erreur:<br />".$e->getMessage());
}
if($i == 0){
  try{
    $res = $resQrySel->fetchAll(PDO::FETCH_OBJ);
  } catch (PDOException $e){
    die("Erreur lors du traitement de la ressource: <br />".$e->getMessage());
  }
  foreach($res as $a=>$b){
    echo "Enregistrement numéro ".$a."<br />";
    foreach($b as $cle=>$valeur){
      echo $cle." = ".$valeur."<br />";
    }
  }
}

echo 'Nombre de requêtes effectuées: '.$connec->getnbrQuery();
si je fait une mauvaise requête je n'ai aucune erreur PDO...
je croit que j'ai du mal saisir une notion là...

Mammouth du PHP | 983 Messages

26 nov. 2006, 12:46

<?php
class MyPDO extends PDO{
	static $qriesCount = 0;
	public function __construct($dsn, $user, $pass){
		try{
			parent::__construct($dsn, $user, $pass);
		}
		catch(PDOException $e){
			throw $e;
   	}
   }
   public function query($qry){
   	try{
   		self::$qriesCount++;
   		return(parent::query($qry));
   	}
   	catch(Exception $eQry){
   		throw $eQry;
   	}
   }
   public function getQueryCount(){
   	return (self::$qriesCount);
   }
}
$dsn = 'mysql:host=localhost; dbname=test';
$user = 'xxx';
$passWd = 'yyy';
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 />';
$qrySel = 'SELECT COUNT(*) nombre FROM `livres`';
for($i = 0; $i < 3; $i++){
	$resQrySel = $cnx->query($qrySel);
	if($i == 0){
		$nbrRangs = $resQrySel->fetchAll(PDO::FETCH_OBJ);
		echo 'Valeur trouv&eacute;e = ' . $nbrRangs[0]->nombre. '<br />';
	}
	echo 'Requ&ecirc;tes : ' . $cnx->getQueryCount() . '<br />';
}
?>
Juste pour information, il se sert à rien de faire un try / catch dans le constructeur si le catch ne fait que renvoyer l'exception. Autant ne pas entourer le constructeur par un bloc try / catch ;)

ViPHP
ViPHP | 1961 Messages

26 nov. 2006, 13:47

Juste pour information, il se sert à rien de faire un try / catch dans le constructeur si le catch ne fait que renvoyer l'exception. Autant ne pas entourer le constructeur par un bloc try / catch ;)
Je ne suis pas entièrement d'accord avec toi.
Comme je l'ai expliqué plus haut, c'est pas le rôle du constructeur de traiter l'exception, mais il doit en informormer "l'appelant" ($var = new Class()) c'est lui devra le faire.
Si je ne transmets pas l'exception (pas de throw, donc pas de try/catch) même si "l'appelant" entoure la demande d'instentiation par le block "ty/catch" il recevra un joli message de PHP du style
Fatal error: Uncaught exception 'PDOException' with message '....'
Je ne suis pas sur que ce soit acceptable.
si je fait une mauvaise requête je n'ai aucune erreur PDO...
Je regarde ça, mais ça me semble 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 | 1961 Messages

26 nov. 2006, 17:10

Re,
Désolé d'avoir répondu aussi tardivement mais des fois en est pas maître de son temps.

Comme MySQL, PDO par défaut n'affiche pas les messages d'erreur mais elle les stocke et sont récupérables via les méthodes $dbh->errorCode() et $dbh->errorInfo()

Elle offre plusieurs façons de gèrer les erreurs :
- Pas d'affichage (par défaut)
- En mode classique.
- En levant des exceptions.

Pour modifier le mode par défaut, PDO dispose d'une méthode : $dbh->setAttribute()
Cette méthode reçoi deux paramètres qui sont des constantes PDO
Le premier paramètre représente l'attribut a modifier, dans nôtre cas PDO::ATTR_ERRMOD
Le second le mode de gestion
- PDO::ERRMODE_SILENT (par défaut)
- PDO::ERRMODE_WARNING (Mode classique)
- PDO::ERRMODE_EXCEPTION
Donc pour résoudre ton PB il sufis d'ajouter au constructeur la méthode, ce qui nous donnerais QQ chose du style
/**
	 * 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;
   	}
   }
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