Discussion:
PDO et erreur
(trop ancien pour répondre)
Une Bévue
2011-11-10 09:25:24 UTC
Permalink
je simule volontairement une erreur en appellant une base de donnée qui
n'existe pas en tant que fichier.
un fichier de base de donnée vide est créé, normal.
Mais ensuite j'envoie une requête sur cette base vide :
$res=$db->query('SELECT ROWID, * FROM categories');
try{
while($row=$res->fetch()){
print_r($row);
echo "<br />";
}
}catch (PDOException $e){
echo 'Connection failed: ' . $e->getMessage();
}

Et, bien sûr, j'ai une erreur :
Fatal error: Call to a member function fetch() on a non-object in
/Users/yt/Sites/landp/landp-pdo-test.php on line 6
malgré le try / catch qui entoure la ligne fautive :
while($row=$res->fetch()){

D'où, ma question, comment gérer l'erreur dans ce cas ?
--
« Dites nous ce dont vous avez besoin ,
on vous expliquera comment vous en passer ! »
(Coluche)
Olivier Miakinen
2011-11-10 10:54:35 UTC
Permalink
Bonjour,
Post by Une Bévue
$res=$db->query('SELECT ROWID, * FROM categories');
try{
while($row=$res->fetch()){
Tu n'as pas testé le code de retour de query, avant de l'utiliser
comme si c'était un PDOStatement. C'est mal.©
Post by Une Bévue
D'où, ma question, comment gérer l'erreur dans ce cas ?
Il suffit de tester les codes d'erreur prévus et signalés dans la doc.

<cit. http://fr2.php.net/manual/fr/pdo.query.php>
Valeurs de retour
PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.
</cit.>

Cordialement,
--
Olivier Miakinen
Une Bévue
2011-11-10 13:03:35 UTC
Permalink
Post by Olivier Miakinen
Tu n'as pas testé le code de retour de query, avant de l'utiliser
comme si c'était un PDOStatement. C'est mal.©
Post by Une Bévue
D'où, ma question, comment gérer l'erreur dans ce cas ?
Il suffit de tester les codes d'erreur prévus et signalés dans la doc.
<cit.http://fr2.php.net/manual/fr/pdo.query.php>
Valeurs de retour
PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.
</cit.>
Ah OK, suis-je bête, merci beauc
oup, je vais lire cette littérature...

Mon but est de rendre compatible mon appli entre le php de free qui
n'utilise que PDO et le php sur Mac OS X où je peux utiliser SQLite3
directement.

MAIS, d'après ce que j'ai lu sur un manuel php, les prochaines versions
d'icelui ne permettront la manipulation d'une base qu'à travers PDO, la
gestion directe ne sera plus supportée...

c'est bien vrai ???
Une Bévue
2011-11-10 17:25:09 UTC
Permalink
Post by Olivier Miakinen
Bonjour,
Post by Une Bévue
$res=$db->query('SELECT ROWID, * FROM categories');
try{
while($row=$res->fetch()){
Tu n'as pas testé le code de retour de query, avant de l'utiliser
comme si c'était un PDOStatement. C'est mal.©
Ben, finalement, je ne comprends pas ce que tu me dis là ou je ne
comprends pas le manuel, ou pire, les deux...

Je lis :
PDO::query() exécute une requête SQL en appelant une seule fonction,
retourne le jeu de résultats (s'il y en a) retourné par la requête en
tant qu'objet PDOStatement.
à l'adresse :
<http://fr2.php.net/manual/fr/pdo.query.php>

Ben, c'est bien une "PDOStatement" mon $res=$db->query('SELECT ROWID, *
FROM categories');

je dois dire qu'avant je faisais un :
if($res) {
while($row=$res->fetch()){
...

et que $res était tjs à 1 même quand je provoquait volontairement une
certaine erreur (pas de base en tant que fichier donc pas de table
categories à lire).

Alors que la doc dit :
Valeurs de retour

PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.
Post by Olivier Miakinen
Post by Une Bévue
D'où, ma question, comment gérer l'erreur dans ce cas ?
Il suffit de tester les codes d'erreur prévus et signalés dans la doc.
<cit. http://fr2.php.net/manual/fr/pdo.query.php>
Valeurs de retour
PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.
</cit.>
donc je devrais plutôt tester le code de retour de :


car je lis :
PDO::errorCode() retourne uniquement les codes erreurs pour les
opérations exécutées directement sur le gestionnaire de la base de
données. Si vous créez un objet PDOStatement avec la fonction
PDO::prepare() ou la fonction PDO::query() et que vous invoquez une
erreur sur le gestionnaire de requête, PDO::errorCode() ne retournera
pas cette erreur. Vous devez appeler PDOStatement::errorCode() pour
retourner le code erreur pour une opération exécutée sur un gestionnaire
de requête particulier.


à la page :
<http://fr2.php.net/manual/fr/pdo.errorcode.php>

Donc, si j'ai bien compris, je devrais plutôt faire :

$db=new PDO("sqlite:fichier-qui-n-existe-pas.db");
// le fichier "sqlite:fichier-qui-n-existe-pas.db" est créé,
// mais il est vide de toute table
$res=$db->query('SELECT ROWID, * FROM categories');

if($res)[
while($row=$res->fetch()){
print_r($row);
echo "<br />";
}
} else {
// une erreur c'est produite car $res est à false
// see <http://fr2.php.net/manual/fr/pdostatement.errorinfo.php>
echo "\nPDOStatement::errorCode(): ";
print $res->errorCode();
$info=$res->errorInfo();
print_r($info);
}

C'est ça ?


En fait ce qui était faux, c'était mon :
} catch (PDOException $e){
echo 'Connection failed: ' . $e->getMessage();
}

qui n'est valable qu'au niveau de :

$db=new PDO("sqlite:fichier-qui-n-existe-pas.db");

laquelle ligne ne produit pas d'erreur...
avec SQLite, puisque s'il n'existe pas, le fichier est créé.


bon, je poste et je teste ça...
Olivier Miakinen
2011-11-10 18:53:50 UTC
Permalink
Bonjour,

Tout d'abord je précise que je n'ai fait que lire la doc, et qu'il
ne s'agit pas d'une expérience personnelle. Si la doc est fausse,
il ne faudra pas m'en vouloir si mes conseils sont erronés.
Post by Une Bévue
Ben, finalement, je ne comprends pas ce que tu me dis là ou je ne
comprends pas le manuel, ou pire, les deux...
Les deux doivent aller ensemble, à moins bien sûr que ce soit moi qui
n'aie pas compris le manuel.
Post by Une Bévue
PDO::query() exécute une requête SQL en appelant une seule fonction,
retourne le jeu de résultats (s'il y en a) retourné par la requête en
tant qu'objet PDOStatement.
<http://fr2.php.net/manual/fr/pdo.query.php>
Ben, c'est bien une "PDOStatement" mon $res=$db->query('SELECT ROWID, *
FROM categories');
if($res) {
while($row=$res->fetch()){
...
C'est en gros ce que je suggérais en citant la doc, et c'est aussi ce
qu'a suggéré SAM.
Post by Une Bévue
et que $res était tjs à 1 même quand je provoquait volontairement une
certaine erreur (pas de base en tant que fichier donc pas de table
categories à lire).
À 1 ??? Je suppose que tu veux dire « différent de FALSE », ce qui est
quand même différent. Ton message d'erreur parlait de « non-objet », or
d'après la doc on ne peut avoir un non-objet que si la valeur retournée
est FALSE.
Post by Une Bévue
Valeurs de retour
PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.
Ben c'est qu'est-ce que j'dis !
Post by Une Bévue
Post by Olivier Miakinen
Post by Une Bévue
D'où, ma question, comment gérer l'erreur dans ce cas ?
Il suffit de tester les codes d'erreur prévus et signalés dans la doc.
<cit. http://fr2.php.net/manual/fr/pdo.query.php>
Valeurs de retour
PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.
</cit.>
Le code de retour de... ?
Post by Une Bévue
[...]
<http://fr2.php.net/manual/fr/pdo.errorcode.php>
$db=new PDO("sqlite:fichier-qui-n-existe-pas.db");
// le fichier "sqlite:fichier-qui-n-existe-pas.db" est créé,
// mais il est vide de toute table
$res=$db->query('SELECT ROWID, * FROM categories');
Voilà encore un cas où tu utilises une variable sans savoir si
elle est correcte. D'après la doc, $db ne peut pas valoir FALSE,
mais le new PDO peut lever une exception à gérer avec try-catch
(à moins que ça n'avorte l'exécution si l'exception n'est pas
traitée ?).
Post by Une Bévue
if($res){
Oui, ça me semble bien.
Post by Une Bévue
while($row=$res->fetch()){
print_r($row);
echo "<br />";
}
} else {
// une erreur c'est produite car $res est à false
// see <http://fr2.php.net/manual/fr/pdostatement.errorinfo.php>
echo "\nPDOStatement::errorCode(): ";
print $res->errorCode();
$info=$res->errorInfo();
print_r($info);
}
C'est ça ?
} catch (PDOException $e){
echo 'Connection failed: ' . $e->getMessage();
}
$db=new PDO("sqlite:fichier-qui-n-existe-pas.db");
laquelle ligne ne produit pas d'erreur...
avec SQLite, puisque s'il n'existe pas, le fichier est créé.
Ah, ok. Il n'empêche que ce serait plus propre si tu le mettais.
Post by Une Bévue
bon, je poste et je teste ça...
D'accord, tiens-nous au courant !
Une Bévue
2011-11-11 06:28:48 UTC
Permalink
Post by Olivier Miakinen
D'accord, tiens-nous au courant !
Bon le code (qui marche si je ne provoque pas d'erreur volontairement) :

try {
$db=new PDO("sqlite:../landp.db");
$res=$db->query('SELECT ROWID, * FROM categories');
if($res){
while($row=$res->fetch()){
print_r($row);
echo "<br />";
}
}else{
echo "\nPDOStatement::errorCode(): ";
print $res->errorCode();
echo "\nPDOStatement::errorInfo():\n";
$arr=$res->errorInfo();
print_r($arr);
}
$db=null; // fermeture connexion
} catch (PDOException $e) {
print "Erreur !: " . $e->getMessage() . "<br/>";
die();
}

- 1 - je n'ai jamais de "PDOException" même si le fichier
"../landp.db" n'esxiste pas;

- 2 - si je provoque une erreur en mettant :
$db=new PDO("sqlite:../landp-fichier-inexistant.db");

J'ai le résultat :
PDOStatement::errorCode():
Fatal error: Call to a member function errorCode() on a non-object in
/home/mfj/Sites/landp/php/pdo_cat_test.php on line 33

ce qui est plutôt bidonnant...

notes bien que je n'ai jamais fait de test sur $db puisque dans un try /
catch.
Olivier Miakinen
2011-11-11 07:10:34 UTC
Permalink
Post by Une Bévue
[...]
if($res){
while($row=$res->fetch()){
print_r($row);
echo "<br />";
}
}else{
echo "\nPDOStatement::errorCode(): ";
print $res->errorCode();
[...]
- 1 - je n'ai jamais de "PDOException" même si le fichier
"../landp.db" n'esxiste pas;
$db=new PDO("sqlite:../landp-fichier-inexistant.db");
Fatal error: Call to a member function errorCode() on a non-object in
/home/mfj/Sites/landp/php/pdo_cat_test.php on line 33
ce qui est plutôt bidonnant...
ce qui est plutôt logique !

Enfin, réfléchis : tu ne peux pas appeler $res->fetch() parce que $res
n'est pas un PDOStatement (il vaut FALSE) ; comment dans ce cas peux-tu
imaginer pouvoir appeler $res->errorCode() ? FALSE->errorCode() ???
Post by Une Bévue
notes bien que je n'ai jamais fait de test sur $db puisque dans un try /
catch.
Ok.
Une Bévue
2011-11-11 10:10:57 UTC
Permalink
Post by Olivier Miakinen
ce qui est plutôt logique !
Enfin, réfléchis : tu ne peux pas appeler $res->fetch() parce que $res
n'est pas un PDOStatement (il vaut FALSE) ; comment dans ce cas peux-tu
imaginer pouvoir appeler $res->errorCode() ? FALSE->errorCode() ???
euh, ce n'est pas fetch qui est à false mais $res (càd $db->query(...))

ensuite la doc dit bien :
PDOStatement->errorCode

(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0)

PDOStatement->errorCode — Récupère le SQLSTATE associé lors de la
dernière opération sur la requête

Report a bug
cf. <http://fr2.php.net/manual/fr/pdostatement.errorcode.php>

exemple donné avec prepare mais query est équivalent<:

Exemple #1 Détermine la catégorie de l'erreur qui survient
<?php
/* Provoque une erreur -- la table BONES n'existe pas */
$err = $dbh->prepare('SELECT skull FROM bones');
$err->execute();

echo "\nPDOStatement::errorCode(): ";
print $err->errorCode();
?>ut à fait mon cas de figure...

ET, à la page :
<http://fr2.php.net/manual/fr/pdo.query.php>

Valeurs de retour

PDO::query() retourne un objet PDOStatement, ou FALSE si une erreur
survient.

????



ce qui est to
Antoine Polatouche
2011-11-11 14:10:29 UTC
Permalink
Post by Une Bévue
Post by Olivier Miakinen
ce qui est plutôt logique !
Enfin, réfléchis : tu ne peux pas appeler $res->fetch() parce que $res
n'est pas un PDOStatement (il vaut FALSE) ; comment dans ce cas peux-tu
imaginer pouvoir appeler $res->errorCode() ? FALSE->errorCode() ???
euh, ce n'est pas fetch qui est à false mais $res (càd $db->query(...))
Essaye de comprendre ce qu'Olivier te dit !!!

$res = FALSE

Tu appelles FALSE->errorCode()

PDO n'a rien à voir dans l'histoire.

FALSE->nimportequoi() te donnera toujours
Fatal error: Call to a member function nimportequoi() on a non-object

Erreur que tu peux intercepter dans une exception, mais pas dans une
PDOException.
Une Bévue
2011-11-12 06:51:08 UTC
Permalink
Post by Antoine Polatouche
Essaye de comprendre ce qu'Olivier te dit !!!
$res = FALSE
Tu appelles FALSE->errorCode()
PDO n'a rien à voir dans l'histoire.
FALSE->nimportequoi() te donnera toujours
Fatal error: Call to a member function nimportequoi() on a non-object
Erreur que tu peux intercepter dans une exception, mais pas dans une
PDOException.
non, j'ai très bien compris ce que dit Olivier et ce que dit la doc, si :
$res=$db-query(...)

est à false, preuve qu'il y a une erreur, je ne peux pas récupérer le
code de l'erreur.

MAIS la docum que j'ai cité dit le contraire, enfin ne dit pas ça, dit
en tk qu'on peut trécupérer l'erreur.

je souhaitais récupérer le code d'erreur, je vois que ce n'est pas
possible...

D'ailleurs je me suis aperçu hier soir que ce script fonctionnait
différemment sur deux xubuntu 11.10, je dois investiguer à ce sujet.
Pour l'un pas d'erreur quand je tente de me connecter à une base sqlite
qui n'existe pas, la fichier de la base est créé, pour l'autre j'ai le
message d'erreur qui est retourné.
Antoine Polatouche
2011-11-12 18:12:41 UTC
Permalink
Post by Une Bévue
$res=$db-query(...)
est à false, preuve qu'il y a une erreur, je ne peux pas récupérer le
code de l'erreur.
MAIS la docum que j'ai cité dit le contraire, enfin ne dit pas ça, dit
en tk qu'on peut trécupérer l'erreur.
La doc que tu cites dit comment récupérer le statut d'une connexion de
base de donnée, ton problème est que tu n'as pas de connexion !
Post by Une Bévue
je souhaitais récupérer le code d'erreur, je vois que ce n'est pas
possible...
Est-ce que tu as essayé de mettre $db = new PDO(...) dans un bloc
d'exception ?
Post by Une Bévue
D'ailleurs je me suis aperçu hier soir que ce script fonctionnait
différemment sur deux xubuntu 11.10, je dois investiguer à ce sujet.
Pour l'un pas d'erreur quand je tente de me connecter à une base sqlite
qui n'existe pas, la fichier de la base est créé, pour l'autre j'ai le
message d'erreur qui est retourné.
Quel message d'erreur ?

(problème de droits d'écriture de www-data ?)
Une Bévue
2011-11-13 06:37:06 UTC
Permalink
Post by Antoine Polatouche
Quel message d'erreur ?
SQLSTATE[HY000] [14] unable to open database file

quand le fichier base de données n'existe pas.


Bon, j'ai trouvé ce qu'il faut faire :

try {
$db=new PDO("sqlite:landp.db"); // 1
$res=$db->query('SELECT ROWID, * FROM kategories'); // 2
if($res){
while($row=$res->fetch()){
print_r($row);
}
}else{
echo "\nPDOStatement::errorCode(): ";
print $db->errorCode();
echo "\nPDOStatement::errorInfo():\n";
$arr=$db->errorInfo();
print_r($arr);
}
echo $html;
$db=null; // fermeture connexion
} catch (PDOException $e) {
print "Erreur !: " . $e->getMessage() . "<br/>";
die();
}
?>
si en "// 1" j'ai une erreur, le fichier n'existe pas, je récupère bien
l'erreur qu niveau du catch, testé sur un ordi seulement.

si en "// 2", comme ici, j'ai une autre erreur, la table kategories
n'existe pas je récupère l'erreur dans le else.

C'est l'exemple donné à la page :
<http://fr2.php.net/manual/fr/pdostatement.errorcode.php>
qui est inexact.

au lieu de :
$err = $dbh->prepare('SELECT skull FROM bones');
$err->execute();

echo "\nPDOStatement::errorCode(): ";
print $err->errorCode();

il faut écrire à la dernière ligne :
print $dbh->errorCode();
______^^^^_____________
puisque, comme l'a vu Olivier $err est à false, on ne peut rien en
sortir d'autre.
Antoine Polatouche
2011-11-13 18:26:47 UTC
Permalink
Post by Une Bévue
<http://fr2.php.net/manual/fr/pdostatement.errorcode.php>
qui est inexact.
$err = $dbh->prepare('SELECT skull FROM bones');
$err->execute();
echo "\nPDOStatement::errorCode(): ";
print $err->errorCode();
print $dbh->errorCode();
______^^^^_____________
puisque, comme l'a vu Olivier $err est à false, on ne peut rien en
sortir d'autre.
L'exemple est bon, et dans ce cas $err ne va pas être à false:

$err = $dbh->prepare('SELECT skull FROM bones');
retourne un objet PDOStatement valide, pour peu que $dbh soit valide (ce
qui doit être vérifié avant!)

$err->execute();
retourne false car la table n'existe pas, mais $err est toujours valide
et $err->errorCode() retourne le code d'erreur.

C'est sans doute le nom de la variable qui te trompe:

$statement = $dbh->prepare('SELECT skull FROM bones');
if(! $statement->execute() )
{
echo "\nPDOStatement::errorCode(): ";
print $statement->errorCode();
}

La différence entre prepare et query, c'est que prepare ne va pas
retourner false car elle ne teste pas la validité de la requête, donc
l'objet PDOStatement va être valide.
Une Bévue
2011-11-13 19:03:17 UTC
Permalink
Post by Une Bévue
Post by Une Bévue
<http://fr2.php.net/manual/fr/pdostatement.errorcode.php>
qui est inexact.
$err = $dbh->prepare('SELECT skull FROM bones');
$err->execute();
echo "\nPDOStatement::errorCode(): ";
print $err->errorCode();
print $dbh->errorCode();
______^^^^_____________
puisque, comme l'a vu Olivier $err est à false, on ne peut rien en
sortir d'autre.
$err = $dbh->prepare('SELECT skull FROM bones');
retourne un objet PDOStatement valide, pour peu que $dbh soit valide (ce
qui doit être vérifié avant!)
$err->execute();
retourne false car la table n'existe pas, mais $err est toujours valide
et $err->errorCode() retourne le code d'erreur.
$statement = $dbh->prepare('SELECT skull FROM bones');
if(! $statement->execute() )
{
echo "\nPDOStatement::errorCode(): ";
print $statement->errorCode();
}
La différence entre prepare et query, c'est que prepare ne va pas
retourner false car elle ne teste pas la validité de la requête, donc
l'objet PDOStatement va être valide.
ok, pigé, merci.
Dans mon cas, je pense qu'il n'y a pas besoin de prépare, l'utilisation de
la bd n'est intense du tout.
--
Une Bévue
SAM
2011-11-10 11:52:27 UTC
Permalink
Post by Une Bévue
je simule volontairement une erreur en appellant une base de donnée qui
n'existe pas en tant que fichier.
un fichier de base de donnée vide est créé, normal.
$res=$db->query('SELECT ROWID, * FROM categories');
try{
while($row=$res->fetch()){
print_r($row);
echo "<br />";
}
}catch (PDOException $e){
echo 'Connection failed: ' . $e->getMessage();
}
Fatal error: Call to a member function fetch() on a non-object in
/Users/yt/Sites/landp/landp-pdo-test.php on line 6
while($row=$res->fetch()){
D'où, ma question, comment gérer l'erreur dans ce cas ?
Je ne connais rien au PHP et encore moins pour ses appels à BdD,

if($res=$db->query('SELECT ROWID, * FROM categories'))
try{

non ?

ou bien (en glissant sur l'erreur) :

if(@$res=$db->query('SELECT ROWID, * FROM categories'))
try{


sinon

peut-être

$res=$db->query('SELECT ROWID, * FROM categories');
try{
while(@$row=$res->fetch()){

ou ?
$res=$db->query('SELECT ROWID, * FROM categories');
try{
while($row=$res->@fetch()){

???


Qu'en disent-ils sur le NG du PHP ?
--
Stéphane Moriaux avec/with iMac-intel
Continuer la lecture sur narkive:
Loading...