Page 1 sur 2

Erreur sur foreach(...)

Posté : 18 juin 2007, 16:42
par aandre2937
D'avance pardon, je ne suis pas encore très avancé en PHP5. Ici j'utilise SQLite 3.
J'ai entré la séquence suivante:
$sql = 'SELECT * FROM clefs LIMIT 10';
foreach ($dbh->query($sql) as $row) {
	for($compte =0; $compte=5; $compte++) echo $row[$compte];
	echo '<br>';
}
Et j'obtiens:
Warning: Invalid argument supplied for foreach() in C:\www\dbtutor\sqlite_clefs.php on line 26
J'ai parcouru l'aide PHP5 en ligne et mon bouquin "PHP5 avancé". Je ne parviens pas à comprendre où est l'erreur. J'ai aussi simplifié la structure comme suit:
$sql = 'SELECT * FROM clefs LIMIT 10';
$res = $dbh->query($sql);
foreach ($res as $row) {
	for($compte =0; $compte=5; $compte++) echo $row[$compte];
	echo '<br>';
}
J'obtiens la même erreur. Quelqu'un pourrait-il (elle) me dire en quoi mon foreach() est mal formé?

Merci d'avance.

Posté : 18 juin 2007, 16:57
par Cyrano
Pose-toi la question suivante : quel type de paramètre attend la fonction foreach() ?

Et selon ta réponse : est-ce que ça t'ouvre des horizons quant à la raison de l'erreur ? Comment définir si le paramètre est correct AVANT de lancer la boucle ?

Je te laisse réfléchir à tout ça, la réponse devrait te sauter à la figure comme le bouchon d'une bouteille de champagne qu'un malotru aurait secoué vigoureusement :mrgreen:

Posté : 18 juin 2007, 18:03
par aandre2937
Je bosse là-dessus depuis que vous avez posté votre réponse.
Pose-toi la question suivante : quel type de paramètre attend la fonction foreach() ?
D'après ce que j'ai pu relire, foreach($res as $row) traite le tableau $res et assigne la valeur courante à $row. Le tableau $res est défini comme le résultat de la requête de sélection sur la table. Ma syntaxe m'a l'air conforme à tous les exemples de mes bouquins et de l'aide en ligne.
Et selon ta réponse : est-ce que ça t'ouvre des horizons quant à la raison de l'erreur ? Comment définir si le paramètre est correct AVANT de lancer la boucle ?
Non, je ne vois vraiment pas pourquoi çà ne marche pas!

Posté : 18 juin 2007, 18:15
par zeus
Si tu sais que foreach() attend un tableau et que tu as un message d'erreur te disant que l'argument passé à foreach() n'est pas valide, il faut que tu commences par vérifier que $dbh->query($sql); te retourne bien un tableau. ;)
C'est un réflexe de développement qu'il faut avoir :D

pour celà, je te conseille d'utiliser var_dump() qui affiche le type et le contenu d'une variable.
$sql = 'SELECT * FROM clefs LIMIT 10';
$res = $dbh->query($sql);
var_dump($res);

Posté : 18 juin 2007, 18:55
par AB
mysql_fetch_assoc() ou mysql_fetch_row() ou mysql_fetch_array()

Posté : 18 juin 2007, 19:00
par Cyrano
mysql_fetch_assoc() ou mysql_fetch_row() ou mysql_fetch_array()
Pour quoi faire ? Il utilise une classe de connexion, rien ne nous indique que la méthode appelée ne retourne pas directement un tableau de données : si son code est logique, c'est précisément ce qui devrait se passer. Et sinon, l'erreur vient effectivement de là, mais c'est ce qu'il faut amener notre ami à découvrir par ses propres déductions logiques :-k

Posté : 18 juin 2007, 19:00
par aandre2937
Il y a un moment, j'avais essaye, en imitation d'un exemple de PHP5 avancé, de déclarer:
$sth = $dbh->query($sql);
$res = $sth->fetch(PDO::FETCH_BOTH);
Mais le résultat avait été:
Fatal error: Call to a member function fetch() on a non-object in C:\www\dbtutor\sqlite_contacts.php on line 22
Je ne vois vraiment pas comment m'y prendre.

En fait, auparavant, j'utilisais ACCESS. Mais ACCESS est un logiciel propriétaire, et dans les bleds africains où je travaille d'habitude, on n'a pas ACCESS, ou alors c'est qu'il est piraté. C'est pour proposer une alternative libre (et légale) que je passe autant de temps à étudier la mise en oeuvre de xhtml / php/ xxxSQL. Je suis ingénieur sanitaire, et pas informaticien, même si j'ai commencé à coder en 1972.

Posté : 18 juin 2007, 19:08
par Cyrano
On va enlever quelques cailloux de ton chemin ;)

Lorsque tu rencontres un bug dans le déroulement de l'exécution d'un code, il est logique de remonter jusqu'au point où le fonctionnement est normal et attendu : l'erreur se trouve entre ce point et le moment où le résultat ne correspond pas du tout à ce qui a été prévu.

Ta requête retourne false, ok : pourquoi ? As-tu testé ta requête directement avec phpMyAdmin par exemple afin de vérifier la validité de cette requête et sinon voir les messages d'erreur retournés par MySQL ? La requête étant basique, s'il n'y a pas d'erreur sur le nom de la table, alors à ce stade tout est normal et c'est entre l'appel de mysql_query et ton affichage qu'il y a une erreur : inspecte ta méthode de classe : est-ce que tu n'as rien oublié quelque part ?

Éventuellement, affiche-nous le code de cette méthode ...

Posté : 18 juin 2007, 19:33
par aandre2937
As-tu testé ta requête directement avec phpMyAdmin par exemple afin de vérifier la validité de cette requête et sinon voir les messages d'erreur retournés par MySQL ?


Incidemment, j'utilise SQLite pour m'affranchir temporairement des contraintes d'identification rencontrées sur MySQL, et a fortiori postgreSQL. En ligne de commande j'obtiens le résultat voulu, avec SQL Manager aussi. C'est vrai que la table est simplissime et la requête élémentaire.
inspecte ta méthode de classe : est-ce que tu n'as rien oublié quelque part ? Éventuellement, affiche-nous le code de cette méthode ...
Là je ne comprends plus ce qu'il faut faire. Il y a quelques jours, j'avais fait le même essai en programmation procédurale, et j'avais obtenu l'affichage (brut) de ma requête sans déclaration particulière. Comme j'ai progressé dans mon bouquin où l'on explique que la programmation d'avenir est la POO, je cherche à la comprendre, sinon la maîtriser. Je n'ai rien trouvé, dans les exemples que j'ai essayés, qui ressemble à une déclaration de classe et ses méthodes.

Posté : 18 juin 2007, 19:42
par Cyrano
Ok, alors question subsidiaire : est-ce quelqu'un a déjà eu l'idée de t'expliquer ce qu'on appelle des propriétés et des méthodes de classe ? Parce que si ce sont pour toi des termes abstraits voire si tu as l'impression qu'on est des gourous psalmodiant des incantations absconses en regardant des lignes de commande sur des moniteurs en noir et blanc, on est peut-être passé un peu trop rapidement à un stade où tu es largué : en clair, tu as loupé une marche. Quand on descend un escalier, le plus dangereux, c'est de louper la première marche :gla:

Posté : 18 juin 2007, 20:15
par AB
Et sinon, l'erreur vient effectivement de là, mais c'est ce qu'il faut amener notre ami à découvrir par ses propres déductions logiques :-k
J'avais bien remarqué votre démarche mais je me suis permis de faire une suggestion plus directe car la dernière réponse de Zeus datait de presque 3/4 heure. Et je me suis dit qu'il s'était passé suffisamment de temps pour relancer le débat sans compromettre vos efforts didactiques :wink:

Posté : 18 juin 2007, 20:31
par aandre2937
Ok, alors question subsidiaire : est-ce quelqu'un a déjà eu l'idée de t'expliquer ce qu'on appelle des propriétés et des méthodes de classe ? Parce que si ce sont pour toi des termes abstraits voire si tu as l'impression qu'on est des gourous psalmodiant des incantations absconses en regardant des lignes de commande sur des moniteurs en noir et blanc, on est peut-être passé un peu trop rapidement à un stade où tu es largué : en clair, tu as loupé une marche. Quand on descend un escalier, le plus dangereux, c'est de louper la première marche :gla:
Je crois avoir compris, tout au moins les principes fondateurs de la POO, les classes, leurs propriétés et leurs méthodes. J'ai procédé à plusieurs expérimentations intéressantes en suivant les exemples de deux livres : "PHP5 avancé - 3ème édition" et "Je me lance avec PHP et MySQL". C'est pourquoi la POO a récemment déclenché en moi des harmoniques, alors que mon effort de compréhension, avec C++ depuis 1989, puis plus récemment avec Java avait été obéré par des manuels trop théoriques.

Cependant, je n'ai pas encore trouvé dans les moyens tutoriaux à ma portée, en y incluant l'aide en ligne, comment déclarer cette variable qui recueille les données résultant de la lecture de ma table. Je continue à chercher, mais un coup de pouce ne serait pas de refus.

Soyons clair: je n'attends pas de solution toute faite, mais une méthode qui me permette de surmonter ces difficultés passagères et d'aller plus loin.

PS. Un commentaire supplémentaire. Je vais repartir bientôt pour une nouvelle mission de dix huit mois en brousse, avec des liaisons Internet de piètre qualité. Je devrai donc travailler sur place avec mes acquis et mes bouquins, et ne pourrai plus demander d'aide.

Merci d'avoir eu la patience de me lire.

Posté : 18 juin 2007, 22:38
par Cyrano
Ok, alors revenons un poil en arrière, tu as fais à un moment donné ceci :
$sth = $dbh->query($sql);
$res = $sth->fetch(PDO::FETCH_BOTH);
ça suppose deux choses :
-1- tu utilises un objets distincts, $dbh dans un premier temps, $sth ensuite.
-2- Ton code ne montre aucune des deux instanciations.

Ça implique un problème majeur : tu essayes de récupérer un résultat avec un objet alors que tu as exécuté la requête avec un autre objet...
Il faudrait qu'on voie tes classes d'accès aux données parce que j'avoue que j'ai du mal avec le fonctionnement qui ça sous-entend :-k

Posté : 18 juin 2007, 22:42
par zeus
$sth est le retour de l'exécution de la méthode query() de l'objet $dbh ;)

De plus, j'insite sur mon var_dump() pour savoir ce que retourne cette méthode query().
Tant que nous n'aurons pas cette réponse, nous ne pourrons pas aider notre ami. Je ne sais pas pour vous mais j'aime savoir vers quoi j'emmène quelqu'un quand je lui donne un conseil ;)

Connexion PHP à une base SQLite

Posté : 19 juin 2007, 11:08
par aandre2937
$sth est le retour de l'exécution de la méthode query() de l'objet $dbh ;)
De plus, j'insite sur mon var_dump() pour savoir ce que retourne cette méthode query().
Bonjour,
J'ai passé ma soirée à relire mes bouquins:
PHP5 Avancé (Eyrolles)
Je me lance en PHP et MySQL (MicroApp)
Definitive Guide to SQLite (Apress)
MySQL - Guide de l'Administrateur et Guide officiel (MySQL ab)
ainsi que l'aide en ligne

Je me suis livré également à différents essais dont voici le résultat:

SQLite
Code
<?php

	// Connexion à la base de données
try {
	$dbh = new PDO("sqlite:mescontacts.db");
	$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
	}
catch (PDOException $e){
	die ("Erreur ! " . $e->getMessage());
}
echo '<p>A ce stade, la connection à la base <strong>mescontacts.db</strong> est réussie.</p>';
	// Lecture d'enregistrements
$sql = 'SELECT * FROM contacts ORDER BY nom, prenoms';
$sth = $dbh->query($sql);
if($dbh->query($sql)===FALSE) {
	echo '<p>La requête SQL est erronée</p>';
	echo $sql;
	exit();
}
//  $res = $sth->fetch(PDO::FETCH_BOTH);
var_dump($sth);
foreach($sth as $row) {
	print_r($row);
	echo '<br/>';
}

	// Fermeture de la connexion

$dbh = NULL;
?>
Résultat:
A ce stade, la connection à la base mescontacts.db est réussie.

Warning: PDO::query() [function.PDO-query]: SQLSTATE[HY000]: General error: 1 no such table: contacts in C:\www\dbtutor\sqlite_contacts.php on line 23

Warning: PDO::query() [function.PDO-query]: SQLSTATE[HY000]: General error: 1 no such table: contacts in C:\www\dbtutor\sqlite_contacts.php on line 24

La requête SQL est erronée
SELECT * FROM contacts ORDER BY nom, prenoms
Il va de soi que la base mescontacts.db contient une table contacts de sept champs, accessible par SQL Manager ou en ligne de commande, et que j'y ai placé quelques données tests.

Je précise que lorsque j'active la ligne
$res = $sth->fetch(PDO::FETCH_BOTH);
, sans la détection d'erreur PDO::query() j'obtiens une autre erreur:
Attempt to apply function fetch() on a non-member item
Autre tentative: J'ai aussi déplacé l'appel à la fonction var_dump($sth); pour qu'elle suive immédiatement l'affectation de $sth. Voici le nouvel output d'erreurs:
A ce stade, la connection à la base mescontacts.db est réussie.

Warning: PDO::query() [function.PDO-query]: SQLSTATE[HY000]: General error: 1 no such table: contacts in C:\www\dbtutor\sqlite_contacts.php on line 23

Résultat de var_dump($sth);.......bool(false)

Warning: PDO::query() [function.PDO-query]: SQLSTATE[HY000]: General error: 1 no such table: contacts in C:\www\dbtutor\sqlite_contacts.php on line 27

La requête SQL est erronée
SELECT * FROM contacts ORDER BY nom, prenoms
Dans aucun des bouquins dont je dispose il n'est question de déclarer la structure des données dans une classe, ni d'y développer des méthodes particulières. C'est pourquoi je suis complètement perdu.

MySQL

Je dispose des droits de superU et d'utilisateur lambda, ainsi que les mots de passe appropriés. J'accède à mes tables MySQL par phpmyAdmin ou en ligne de commande.
J'ai exporté cette table mescontacts.db dans MySQL par phpmyAdmin.
J'ai recopié le script ci-dessus dans un second fichier PHP appelé MySQL_contact.php, et j'ai spécifié l'utilisateur et son mot de passe (qui fonctionne avec phpmyAdmin). Cette fois je reçois une erreur de connexion:
Erreur ! SQLSTATE[28000] [1045] Access denied for user 'ODBC'@'localhost' (using password: NO)
Qu'en pensez-vous?