Boucler deux fois sur une même requête?

Mammouth du PHP | 555 Messages

03 janv. 2009, 13:23

Bonjour à tous et bonne année!
Ca faisait longtemps que je n'étais pas venu ici.
Je vais vous exposer un problème que je rencontre fréquemment ici.
Juger plutôt ce code.
<?php
//initialisation de la connexion selection de la bdd...
$sql1 = mysql_query("SELECT a, b, id FROM matable WHERE condition");
while($sql2 = mysql_fetch_array($sql1))
{
 $sql2['a']--;
 $sql2['b']++;
 mysql_query("UPDATE matable SET a = '".$sql2['a']."', b = '".$sql2['b']."' WHERE id = '".$sql2['id']."'");
}
$sql3 = mysql_query("SELECT a, b, id FROM matable WHERE condition");
while($sql4 = mysql_fetch_array($sql3))
{
 $sql4['a']++;
 $sql4['b']--;
 mysql_query("UPDATE matable SET a = '".$sql4['a']."', b = '".$sql4['b']."' WHERE id = '".$sql4['id']."'");
}
?>
On est d'accord ceci fonctionne mes a et b n'auront pas bougés au final, maintenant ceci est embêtant puisque ça m'oblige à aller cherche deux fois mon contenu en table.
Maintenant si je remplace ce code par ces deux là la seconde boucle ne s'effectue pas.
<?php
//initialisation de la connexion selection de la bdd...
$sql1 = mysql_query("SELECT a, b, id FROM matable WHERE condition");
while($sql2 = mysql_fetch_array($sql1))
{
 $sql2['a']--;
 $sql2['b']++;
 mysql_query("UPDATE matable SET a = '".$sql2['a']."', b = '".$sql2['b']."' WHERE id = '".$sql2['id']."'");
}
while($sql4 = mysql_fetch_array($sql1))
{
 $sql4['a']++;
 $sql4['b']--;
 mysql_query("UPDATE matable SET a = '".$sql4['a']."', b = '".$sql4['b']."' WHERE id = '".$sql4['id']."'");
}
?>
<?php
//initialisation de la connexion selection de la bdd...
$sql1 = mysql_query("SELECT a, b, id FROM matable WHERE condition");
while($sql2 = mysql_fetch_array($sql1))
{
 $sql2['a']--;
 $sql2['b']++;
 mysql_query("UPDATE matable SET a = '".$sql2['a']."', b = '".$sql2['b']."' WHERE id = '".$sql2['id']."'");
}
while($sql2)
{
 $sql2['a']++;
 $sql2['b']--;
 mysql_query("UPDATE matable SET a = '".$sql2['a']."', b = '".$sql2['b']."' WHERE id = '".$sql2['id']."'");
}
?>
On est d'accord j'ai pris des incrémentations/décrémentations pour illustrer mes exemples mais il arrive souvent en pratique que dans la première boucle je fasse des tests, remplisse des tableaux sans modifier ma bdd puis qu'entre les deux boucle j'agisse sur ce que j'ai produit dans la première et qu'enfin avec ces nouveaux éléments et dans la seconde boucle j'aille modifier ma bdd selon tel ou tel critère...
Voila si quelqu'un a une idée pour que la seconde boucle fonctionne quand même mais que je n'aie pas à aller re-chercher mes valeurs dans la bdd je suis preneur.
Merci à tous!
A+ et bon surf!!!!

Mammouth du PHP | 1668 Messages

03 janv. 2009, 15:20

Bonjour,
Je pense que le plus simple est de faire comme ça :
<?php
$donnees = array(); // Notre tableau qui contiendra les lignes
$sql1 = mysql_query("SELECT a, b, id FROM matable WHERE condition"); 
while($sql2 = mysql_fetch_array($sql1)) 
{ 
   $donnees[] = $sql2;
   // Une variante très pratique consiste à faire :
   $donnees[$sql2['id']] = $sql2;
}

// Puis tes boucles de traitements :
foreach($donnees as $ligne) // Si tu as appliqué "ma" variante d'insertion tu peux faire : foreach($donnees as $id => $ligne)
{
   // Tes traitements de la première boucle
}
foreach($donnees as $ligne)
{
   // Tes traitements de la première seconde
}
Personnellement en utilisant $pdo->prepare()->execute()->fetchAll(); j'ai directement le résultat obtenu via la boucle "while", et mes requêtes sont sécurisées...

Voilà, bonne journée
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

03 janv. 2009, 15:33

Plutôt que de remonter des données en mémoire inutilement (eh oui, un tableau, c'est des données en mémoire), il vaut mieux utiliser mysql_data_seek() pour remettre ton pointeur de résultat au 1er enregistrement
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Mammouth du PHP | 555 Messages

03 janv. 2009, 15:39

Salut,
Merci c'est effectivement une solution, mais ce que je ne comprends pas c'est que la "réponse" de mysql est contenue dans $sql1, on devrait donc pouvoir l'utiliser autant de fois que l'on veut de manière identique non?
De même $sql2 est un tableau, on devrait pouvoir le réutiliser, le faire dérouler dans la boucle, n'y a-t-il pas une solution moins "bricolée"? (désolé de qualifier ta solution de bricolée mais j'espère bien qu'une solution "native" existe, genre une fonction qui fait dérouler les tableaux...)
En reprenant ta solution, ne pourrait-on faire quelque chose comme ceci?
<?php
$sql1 = mysql_query("SELECT a, b, id FROM matable WHERE condition");
$sql2 = mysql_fetch_array($sql1);
foreach($sql2 as $ligne)
{
   // Tes traitements de la première boucle
}
foreach($sql2 as $ligne)
{
   // Tes traitements de la première seconde
} //...
?> 
Je vais essayer ça je reviens...

EDIT

Je n'avais pas vu ton message Zeus désolé.
La solution que j'ai essayée au dessus ne fonctionne évidemment pas mais la fonction de zeus fonctionne.
La solution à mon problème est donc.
<?php
$sql1 = mysql_query("SELECT a, b, id FROM matable WHERE condition");
while($sql2 = mysql_fetch_array($sql1))
{
 //traitements
}
mysql_data_seek($sql1, 0);
while($sql2 = mysql_fetch_array($sql1))
{
 //traitements
}
?> 
Je mets donc résolu merci à tous! (ca va alléger une bonne partie de mon code ça...)
A+ et bon surf!!!!