Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

PDO et erreur

15 réponses
Avatar
unbewusst.sein
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)

10 réponses

1 2
Avatar
Olivier Miakinen
Bonjour,

Le 10/11/2011 10:25, Une Bévue a écrit :

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

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
Avatar
SAM
Le 10/11/11 10:25, Une Bévue a écrit :
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 ?




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
Avatar
Olivier Miakinen
Le 10/11/2011 11:54, je répondais à Une Bévue :

Tu n'as pas testé le code de retour de query, avant de l'utiliser
comme si c'était un PDOStatement. C'est mal.©



Par ailleurs, tu as fait un crosspost avec suivi dans fr.comp.lang.php
sans signaler le suivi, ce qui a trompé SAM qui croyait répondre dans
fciwa. Ce n'est pas très bien non plus... ;-)

[suivi nulle part, c'était juste pour prévenir les lecteurs de fciwa
que les réponses sont sur fclp]
Avatar
Une Bévue
On 10/11/2011 11:54, Olivier Miakinen wrote:
Tu n'as pas testé le code de retour de query, avant de l'utiliser
comme si c'était un PDOStatement. C'est mal.©

> 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 ???
Avatar
SAM
Le 10/11/11 12:59, Olivier Miakinen a écrit :

Par ailleurs, tu as fait un crosspost avec suivi dans fr.comp.lang.php
sans signaler le suivi, ce qui a trompé SAM qui croyait répondre dans
fciwa.



Ha! Oui! La honte !
Que vont-ils en penser là-bas ?

[suivi nulle part, c'était juste pour prévenir les lecteurs de fciwa
que les réponses sont sur fclp]



Vu!
Personne n'y a encore tenté de corriger mes fantaisies.

--
Stéphane Moriaux avec/with iMac-intel
Avatar
Une Bévue
On 10/11/2011 11:54, Olivier Miakinen wrote:
Bonjour,

Le 10/11/2011 10:25, Une Bévue a écrit :

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

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...
Avatar
Olivier Miakinen
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.

Le 10/11/2011 18:25, Une Bévue a écrit :

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.

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()){
...



C'est en gros ce que je suggérais en citant la doc, et c'est aussi ce
qu'a suggéré SAM.

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.

Alors que la doc dit :
Valeurs de retour

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



Ben c'est qu'est-ce que j'dis !

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 :





Le code de retour de... ?

car je lis :
[...]

à 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');



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

if($res){



Oui, ça me semble bien.

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



Ah, ok. Il n'empêche que ce serait plus propre si tu le mettais.

bon, je poste et je teste ça...



D'accord, tiens-nous au courant !
Avatar
Une Bévue
On 10/11/2011 19:53, Olivier Miakinen wrote:
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.
Avatar
Olivier Miakinen
Le 11/11/2011 07:28, Une Bévue a écrit :

Bon le code (qui marche si je ne provoque pas d'erreur volontairement) :

[...]
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;

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



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

notes bien que je n'ai jamais fait de test sur $db puisque dans un try /
catch.



Ok.
Avatar
Une Bévue
On 11/11/2011 08:10, Olivier Miakinen wrote:
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
1 2