while + foreach pas compatible ?! (2 TT, vivent les topics web)

while + foreach pas compatible ?! (2 TT, vivent les topics web) - PHP - Programmation

Marsh Posté le 16-05-2006 à 00:40:52    

Bonsoir,
une chose surement toute bete:
 
je ne comprends pas pourquoi ceci ne fonctionne pas:

Code :
  1. $req = mysql_query("SELECT... " );
  2. while($donnees = mysql_fetch_assoc($req))
  3. {
  4.     ...
  5. }
  6. foreach($donnees as $valeur)
  7. {
  8.     ....
  9. }


 
j'obtiens : Warning: Invalid argument supplied for foreach()
avec la boucle foreach.
 
Quelqu'un peut m'expliquer ?  :??:

Message cité 1 fois
Message édité par Harkonnen le 16-05-2006 à 18:21:36
Reply

Marsh Posté le 16-05-2006 à 00:40:52   

Reply

Marsh Posté le 16-05-2006 à 01:02:41    

Ton tableau $donnees n'est visible que dans ton while (qui cree un tableau contenant les donnees de ta requete pour chaque ligne qu'elle retourne). Si tu veux l'utiliser dans ton foreach il faut declarer ta variable $donnees avant.
Pourquoi utiliser un foreach et un while successivement sur les memes donnees?

Reply

Marsh Posté le 16-05-2006 à 01:18:28    

a d'accord.  
 
Et bien je me sers d'un foreach plus loin dans mon code pour retrouver une valeur de ce tableau.
 
Je suis donc obligé de refaire un while avec mysql_fetch_assoc.

Reply

Marsh Posté le 16-05-2006 à 01:20:46    

zerealfred a écrit :

Ton tableau $donnees n'est visible que dans ton while (qui cree un tableau contenant les donnees de ta requete pour chaque ligne qu'elle retourne). Si tu veux l'utiliser dans ton foreach il faut declarer ta variable $donnees avant.


 
N'importe quoi, l'affectation directe dans la condition d'une boucle ne limite pas la portée de la variable à la seule boucle...
 

papanoramix a écrit :


j'obtiens : Warning: Invalid argument supplied for foreach()
avec la boucle foreach.
 
Quelqu'un peut m'expliquer ?  :??:


 
C'est tout simplement parce qu'au dernier passage dans ta boucle, ta condition doit valoir False. Comme tu fais une affectation, $donnees vaut également false, ce qui n'est pas vraiment le tableau qu'attend un foreach.

Reply

Marsh Posté le 16-05-2006 à 01:22:10    

Ok.
A ta place je declarerais plutot mon tableau  $donnees=mysql_fetch_assoc($req) apres le resultat de la requete et je ferais tous mes traitements avec des foreach.
A toi de voir, il a surement d'autres solutions possibles! ;)

Reply

Marsh Posté le 16-05-2006 à 01:23:46    

Desole naceroth si j'ai induit en erreur, comme quoi on en apprend tous les jours! :)

Reply

Marsh Posté le 16-05-2006 à 01:26:31    

Ok ok, bon je vais voir ce qui cloche.
Merci bien

Reply

Marsh Posté le 16-05-2006 à 01:32:11    

heu en fait je vois pas, si je mets un print_r($donnees) dans mon while j'obtiens:
Array ( [id] => 2 )  
 
et mon foreach n'en veut pas..

Reply

Marsh Posté le 16-05-2006 à 01:41:46    

Lit les réponses qu'on te donne, tu gagnerais beaucoup de temps...

Reply

Marsh Posté le 16-05-2006 à 01:56:19    

J'aimerai bien gagner du temps... ;-)
 
Bon alors je pense pas avoir exclu de réponses, je ne vois pas en quoi ce tableau Array ( [id] => 2 )  vaut false.
 
je suis d'accord avec zerealfred pour ce qui est de declarer le tableau puis faire les boucles, mais j'aimerai quand meme comprendre..

Reply

Marsh Posté le 16-05-2006 à 01:56:19   

Reply

Marsh Posté le 16-05-2006 à 02:08:08    

Au lieu de faire print_r($donnees) essaye plutot print_r($donnees[0]), tu verras peut etre une difference.

Reply

Marsh Posté le 16-05-2006 à 02:50:45    

papanoramix a écrit :

J'aimerai bien gagner du temps... ;-)
 
Bon alors je pense pas avoir exclu de réponses, je ne vois pas en quoi ce tableau Array ( [id] => 2 )  vaut false.
 
je suis d'accord avec zerealfred pour ce qui est de declarer le tableau puis faire les boucles, mais j'aimerai quand meme comprendre..


 
Je te dis que lors de ton dernier passage (une fois qu'il n'y a plus de résultat dans ta table donc), $donnees vaudra false. Si $donnees vaut false tu n'entres pas dans la boucle. Ce n'est donc évidement pas à l'intérieur de la boucle while que tu risques de le voir, le false...
 
Donc, pour vulgariser encore plus :
les valeurs de $donnees au fur et à mesure
Array ( [id] => 1 ) on passe dans la boucle
Array ( [id] => 2 ) on passe dans la boucle
Array ( [id] => 3 ) on passe dans la boucle
...
boolean false, on ne passe pas dans la boucle et on continue jusqu'au foreach
=> erreur, $donnees n'est pas un tableau.
 
Suggestion du soir : revoir les bases, notamment comment fonctionne les boucles et les retours de fonction, parce que visiblement, c'est pas au point.
 

Citation :


print_r($donnees[0]), tu verras peut etre une difference.


 
C'est sûr que vu le premier print_r, celui que tu proposes va lui faire voir une différence. Un message d'erreur, sûrement :D

Reply

Marsh Posté le 16-05-2006 à 03:27:26    

Code :
  1. $req = mysql_query("SELECT... " );
  2. $x = 0;
  3. $donnees = array();
  4. $lesVraisDonnes = array();
  5. while($donnees = mysql_fetch_assoc($req))
  6. {
  7.     $lesVraisDonnes[$x] = $donnees;
  8.     $x++;
  9. }
  10. foreach($lesVraisDonnes as $valeur)
  11. {
  12.     ....
  13. }


Message édité par Djebel1 le 16-05-2006 à 03:27:40
Reply

Marsh Posté le 16-05-2006 à 08:24:04    

si c'est pour reparcourir le même tableau, y'a pas vraiment besoin de le réaffecter non ?
 
autant utiliser mysql_data_seek() et reparcourir les lignes retournées


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 10:33:21    

Sh@rdar a écrit :

autant utiliser mysql_data_seek() et reparcourir les lignes retournées


 
 :jap: En effet, le problème n'a rien à voir avec la portée des variables ou l'utilisation des boucles. C'est tout simplement que mysql_fetch_*** deplace le curseur d'une ligne dans le recordset.
2 solutions :  
1) utiliser mysql_data_seek qui replace le curseur au début du recordset (lourd et peu efficace)
2) stocker les données dans un tableau et parcourir ensuite ce tableau (necessite plus de mémoire mais allège la database)

Reply

Marsh Posté le 16-05-2006 à 10:55:42    

papanoramix > Qu'est-ce qui t'oblige à reparcourir les résultats une deuxième fois ? C'est très peu souvent indispensable.


Message édité par sielfried le 16-05-2006 à 10:56:00

---------------
StarCraft Professional Gaming Database | [Ze Topic] Starcraft/BroodWar
Reply

Marsh Posté le 16-05-2006 à 11:00:33    

smaragdus a écrit :

:jap: En effet, le problème n'a rien à voir avec la portée des variables ou l'utilisation des boucles. C'est tout simplement que mysql_fetch_*** deplace le curseur d'une ligne dans le recordset.
2 solutions :  
1) utiliser mysql_data_seek qui replace le curseur au début du recordset (lourd et peu efficace)
2) stocker les données dans un tableau et parcourir ensuite ce tableau (necessite plus de mémoire mais allège la database)


 
je suis pas d'accord
 
mysql_data_seek est pas lourd ni peu efficace
 
et le coup du tableau allège en rien la base, il s'agit ici de lecture du buffer, y'a pas de relecture de la table ou de rééxécution de la requête


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 11:18:48    

Sh@rdar a écrit :

je suis pas d'accord
 
mysql_data_seek est pas lourd ni peu efficace
 
et le coup du tableau allège en rien la base, il s'agit ici de lecture du buffer, y'a pas de relecture de la table ou de rééxécution de la requête


 
Ca a beau être bufferisé, c'est quand même bien plus lent et lourd. La solution consiste donc à stocker en mémoire (si c'est possible).
Une database ne s'utilise pas comme une mémoire vive, c'est l'évidence même [:dawa]
 
edit : Je viens de faire le test : c'est au moins 8 fois plus lent


Message édité par smaragdus le 16-05-2006 à 11:23:13
Reply

Marsh Posté le 16-05-2006 à 11:24:29    

donne ton test [:dawa]
 


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 11:32:23    

Sh@rdar a écrit :

donne ton test [:dawa]



$result = mysql_query("select * from abonnementsiteinternaute", $cac);
$t[0] = microtime();
while ($obj = mysql_fetch_object($result))
 $tab1[] = $obj;
$t[1] = microtime();  
mysql_data_seek($result, 0);
while ($obj = mysql_fetch_object($result))
 $tab2[] = $obj;
$t[2] = microtime();
foreach($tab2 as $pk => $obj)
 $tab3[] = $obj;
$t[3] = microtime();
?>
 
delta1 = <?php echo ($t[1]-$t[0]) ?><br />  
delta2 = <?php echo ($t[2]-$t[1]) ?><br />  
delta3 = <?php echo ($t[3]-$t[2]) ?><br />  
 


 
et ça affiche :
delta1 = 0.020093
delta2 = 0.022433
delta3 = 0.002944
 
Comme on le voit, la bufferisation n'a aucun effet (c'est même plus lent dans ce cas là mais des fois c'est un poil plus rapide)
 
Voila la prochaine fois, tu éviteras de parler sans savoir  :sarcastic:
 
edit : tu m'excuseras j'ai utilisé mysql_fetch_object mais c'est pareil)


Message édité par smaragdus le 16-05-2006 à 11:35:54
Reply

Marsh Posté le 16-05-2006 à 11:35:57    

tu peux faire les deux traitements séparés ? (2 scripts, 2 copies de tables pour éviter le cache query) ;)
 
 
EDIT : ah, on est déjà plus sur des temps 8 fois plus lents là [:dawa]

Message cité 1 fois
Message édité par Sh@rdar le 16-05-2006 à 11:36:50

---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 11:39:02    

Sh@rdar a écrit :

tu peux faire les deux traitements séparés ? (2 scripts, 2 copies de tables pour éviter le cache query) ;)
 
 
EDIT : ah, on est déjà plus sur des temps 8 fois plus lents là [:dawa]


 
N'essaie pas de te rattraper, tu t'es planté en beauté, tu va pas chpoter pour 6 fois plus lent ou 8 plus, c'est varaible :lol: :lol: :lol:
 
delta1 = 0.020287
delta2 = 0.020156
delta3 = 0.002819
 
7 fois plus lent :lol:

Message cité 1 fois
Message édité par smaragdus le 16-05-2006 à 11:40:28
Reply

Marsh Posté le 16-05-2006 à 11:44:33    

delta1 = 0.024067
delta2 = 0.02215
delta3 = 0.002815
 
lol, 7.8 fois plus lent [:rofl]
 
Au fait qu'est-ce que tu viens me parler d'eviter le cache query ? C'est toi qui justement vante son "efficacité" ? :lol:
 
bref :/

Reply

Marsh Posté le 16-05-2006 à 11:45:20    

je me pose juste des questions, j'ai pas du tout les même résultats
 
sur une table de 2 millions + ligne avec 2 copies identiques  
 
mysql_data_seek()
 

Code :
  1. <?php
  2. function getmicrotime($m) {
  3. list($usec, $sec) = explode(' ',$m);
  4.    return ((float)$usec + (float)$sec);
  5. }
  6. $start = microtime();
  7.    
  8. $Connect = mysql_connect('localhost','***','***');
  9. mysql_select_db('test');
  10. $Query = mysql_query ('SELECT A,B,C,D,E,F,G FROM heavy LIMIT 1000',$Connect);
  11. while ($val = mysql_fetch_row($Query)) {
  12. echo $val[0].' ';
  13. }
  14. for ($i = 1 ; $i <= 10; $i++) {
  15. mysql_data_seek($Query,0);
  16. while ($val = mysql_fetch_row($Query)) {
  17.  echo $val[0].' ';
  18. }
  19. }
  20. $end = microtime();
  21. echo (getmicrotime($end) - getmicrotime($start));
  22. ?>


 
avec un tableau
 

Code :
  1. <?php
  2. function getmicrotime($m) {
  3. list($usec, $sec) = explode(' ',$m);
  4.    return ((float)$usec + (float)$sec);
  5. }
  6. $start = microtime();
  7.    
  8. $Connect = mysql_connect('localhost','***','***');
  9. mysql_select_db('test');
  10. $Query = mysql_query ('SELECT A,B,C,D,E,F,G FROM heavy2 LIMIT 1000',$Connect);
  11. while ($val = mysql_fetch_row($Query)) {
  12. echo $val[0].' ';
  13. $Results[] = $val;
  14. }
  15. for ($i = 1 ; $i <= 10; $i++) {
  16. foreach ($Results AS $val) {
  17.  echo $val[0].' ';
  18. }
  19. }
  20. $end = microtime();
  21. echo (getmicrotime($end) - getmicrotime($start));
  22. ?>


 
j'ai pas les temps que tu donne quelque soit le nombre de ligne ou d'itération...


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 11:49:13    

tu fais des echo et tu demarres le compteur de temps avant le connect ? LOL [:rofl]
 
Plus bidon que ça, je sais pas comment on peut faire :lol:

Reply

Marsh Posté le 16-05-2006 à 11:52:58    

déplace le si tu t'imagine que ça va changer quelque chose..


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 11:53:34    

Sh@rdar a écrit :

déplace le si tu t'imagine que ça va changer quelque chose..


 
Arrête de te foutre de ma gueule et va réviser la doc  :sarcastic:  

Reply

Marsh Posté le 16-05-2006 à 11:57:25    

ah, ça serait la connexion qui serait donc plus lente quand on utilise pas la même fonction [:dawa]


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 11:58:34    

Sh@rdar a écrit :

ah, ça serait la connexion qui serait donc plus lente quand on utilise pas la même fonction [:dawa]


 
Tu te forces à ce point pour pas comprendre que tes mesures sont n'importe quoi ?
Prend un sablier, forcément tu obtiendras un temps identique pour les 2 :lol:
 
edit : ortho


Message édité par smaragdus le 16-05-2006 à 12:52:20
Reply

Marsh Posté le 16-05-2006 à 12:04:12    

utiliser un tableau t'oblige à affecter une variable en plus, forcément si tu compte pas ça dans la mesure..


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 12:06:42    

Sh@rdar a écrit :

utiliser un tableau t'oblige à affecter une variable en plus, forcément si tu compte pas ça dans la mesure..


 
C'est bien pour ça que je fais aussi l'affectation dans la 3ième boucle pour comparer ce qui est comparable :lol:
 
Dis moi, tu as fait l'effort de lire ce que j'ai posté ? Visiblement non :sarcastic:

Message cité 1 fois
Message édité par smaragdus le 16-05-2006 à 12:12:02
Reply

Marsh Posté le 16-05-2006 à 12:14:00    

smaragdus a écrit :

C'est bien pour ça que je fais aussi l'affectation dans la 3ième boucle pour comparer ce qui est comparable :lol:
 
Dis moi, tu as fait l'effort de lire ce que j'ai posté ?  :sarcastic:


 
pour toi affecter une variable dans un foreach() est pareil que dans un mysql_fetch_* ?  
 
essaye comme je t'ai demandé, t'es tellement balèze que tu peux pas te tromper [:dawa]
 
étrangement, mon pauvre test merdique montre toujours que c'est pas plus lent..


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 12:15:24    

Sh@rdar a écrit :


étrangement, mon pauvre test merdique montre toujours que c'est pas plus lent..


LOL on y croit vachement :lol:
 
je t'ai expliqué qu'avec un sablier tu obtiendrais le même temps. T'as pas compris que faire tes mesures avec un echo et le connect au milieu
c'est comme essayer de mesurer le poids de 2 poussins différents à bord d'un 38 tonnes ?
 
C'est en ça que ton test ne vaut rien.
 
38 tonnes + 100 grammes à comparer avec 38 tonnes + 700 grammes, forcement, ça donne quasiment le même poids [:rofl]
Alors qu'un poussin est pourtant 7 fois plus lourd que l'autre.  
 
Bref, belle tentative pour noyer le poisson (heu le poussin, pardon :D )


Message édité par smaragdus le 16-05-2006 à 12:26:29
Reply

Marsh Posté le 16-05-2006 à 12:28:35    

ça te gène tant que ça de faire un test un peu plus rigoureux ?
 
le problème c'est que ton truc revient à comparer data_seek VS foreach alors que le fait d'affecter le tableau pendant le fetching est ce qui fait perdre tout l'avantage du foreach...


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 12:46:06    

Sh@rdar a écrit :

ça te gène tant que ça de faire un test un peu plus rigoureux ?


 
N'inverse pas le roles stp, tu racontes nawak depuis le début.
 

Citation :

le problème c'est que ton truc revient à comparer data_seek VS foreach alors que le fait d'affecter le tableau pendant le fetching est ce qui fait perdre tout l'avantage du foreach...


 
arrête la drogue, tu comprends rien au test de performance  [:zytrafumay]  
Je compare ce qui est comparable et le verdict est sans appel possible : faire un mysql_fetch_ avec un mysql_data_seek est beaucoup plus lent et lourd que de stocker un resultat de requete dejà parcourue une fois. L'affectation pendant ce premier parcours, c'est peanuts comparé à un mysql_fetch lors du deuxième parcours, c'est de la logique.


Message édité par smaragdus le 16-05-2006 à 12:54:49
Reply

Marsh Posté le 16-05-2006 à 12:53:33    

ah mais je suis d'accord avec toi !!
 
faire un foreach sur un tableau est plus rapide que faire un mysql_data_seek
 
 seulement moi je sais que le tableau il va pas sortir d'un chapeau magique, et que son affectation va faire toute la différence (à la fois en mémoire et en temps d'exécution)
 
tu peux bencher tout ce que tu veux, le tableau il va forcément falloir l'affecter pendant le fetching..

Message cité 1 fois
Message édité par Sh@rdar le 16-05-2006 à 12:54:19

---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 12:55:55    

Sh@rdar a écrit :

tu peux bencher tout ce que tu veux, le tableau il va forcément falloir l'affecter pendant le fetching..


 
oui et affecter un tableau, c'est nul comparativement à refaire un mysql_fetch plutôt que de travailler sur le tableau en mémoire. CQFD.
 
C'est ce qu'on appelle programmer proprement et efficacement, un concept qui t'es étranger.


Message édité par smaragdus le 16-05-2006 à 12:58:00
Reply

Marsh Posté le 16-05-2006 à 12:58:12    

oui mais c'est pas encore la même chose que d'affecter un tableau pendant le fetching..  
 
chose que bien sur tu ne prends pas en compte alors que sur un cas pratique tu ne peux pas passer outre..


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le 16-05-2006 à 12:59:01    

Sh@rdar a écrit :

oui mais c'est pas encore la même chose que d'affecter un tableau pendant le fetching..  
 
chose que bien sur tu ne prends pas en compte alors que sur un cas pratique tu ne peux pas passer outre..


 
Pinaille sur des points de détails, il ne te reste que ça pour ne pas mourir de honte.

Reply

Marsh Posté le 16-05-2006 à 13:01:49    

ce détail que tu élude montre que ce que tu raconte est faux, désolé pour toi..
 
ce temps perdu à affecter compense simplement la rapidité du foreach
 
au final, pour faire le même nombre d'itération, les 2 solutions sont soit aussi rapide (peu de lignes) soit mysql_data_seek() est plus rapide (sur beaucoup de lignes)
 
t'as qu'à tester puisque t'es tellement un roxxor


---------------
La musique c'est comme la bouffe, tu te souviens du restaurant dans lequel t'as bien mangé 20 ans plus tôt, mais pas du sandwich d'il y a 5 minutes :o - Plugin pour winamp ©Harkonnen : http://harko.free.fr/soft
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed