Soucis avec modulo

Eléphant du PHP | 153 Messages

22 sept. 2006, 14:28

Bonjour à tous,

Je veux afficher les résultats d'une requête sur 3 colonnes et autant de lignes que necessaire.

J'ai trouvé des topic à ce sujet, je ai appliqué les méthodes (sans trop tout comprendre), mais ça ne focntionne pas, enfin très mal.
L'affichage se fait n'importe comment et les produits sont affichés plusieurs fois. :lol:

Mon code :
echo '<table width="90%" border="0" cellspacing="0" cellpadding="0"><tr>';
$sql = "SELECT catID FROM categories WHERE parent = '$catID'";
$resu = mysql_query($sql);
while ($row = mysql_fetch_array($resu))
	{
		$sql_prod = "SELECT nom FROM produits WHERE catID = '" .$row['catID']. "' ";
		$result_prod = mysql_query($sql_prod);
		while ($row = mysql_fetch_assoc($result_prod))
		{
			$tablo[] = $row;
		}
		for ($i=0; $i<count($tablo); $i++) 
		{
			echo '<td>' .$tablo[$i]['nom']. '</td>';
			if (($i+1) % 3 == 0) 
			{
				// nouvelle ligne 
        			echo "</tr><tr>";
        	}
        }
        while (($i) % 3 != 0) 
        { 
    		// on termine le tableau 
    		echo "<td></td>"; 
    		$i++;
        } 
    }
echo '</tr></table>';
Merci par avance pour votre aide :)

Eléphant du PHP | 413 Messages

22 sept. 2006, 14:40

à mon avis il faudrait ajouter un echo "</tr>" après la terminaison du tableau :
while (($i) % 3 != 0) 
        { 
            // on termine le tableau 
            echo "<td></td>"; 
            $i++;
        }
        echo "</tr><tr>\n";
ça résoudrait ton problème ça ?
--
Goeb

Eléphant du PHP | 153 Messages

22 sept. 2006, 14:46

Euh...
Non, du tout, c'est pire ! :P :D

Merci quand même :wink:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

22 sept. 2006, 15:12

yurrk ?! c'est quoi ces whileforwhile :shock:

Bon, alors commençons par le commencement (mouais.. je vais peut être passé la partie dinosaure et en venir à ce qui nous interesse ;)) Un modulo, c'est tout simplement le reste entier de ta division.
Ex:
18 / 3 = 6, reste 0 (donc 18 modulo 3 ou 18 % 3 = 0)
20 / 3 = 6, reste 2 (donc 20 modulo 3 ou 20 % 3 = 2)

Ce reste est nécessairement entier (ce qui nous arrange d'autant) et nécessairement inférieur à la valeur du diviseur (ben oui, parce que s'il était supérieur, on pourrait encore divisé :)). L'intérêt de cette bestiole, c'est donc qu'il va boucler tout seul au fur et à mesure que le nombre total augmente. Et comme rien ne vaut un bon exemple :

Code : Tout sélectionner

0 % 3 = 0 1 % 3 = 1 2 % 3 = 2 3 % 3 = 0 // et hop, on recommence 4 % 3 = 1 5 % 3 = 2 6 % 3 = 0 // bon je vais peut être pas tous les faire 7 % 3 = 1 ...
Tout ça pour dire que, tu peux diviser en plusieurs colonnes une série d'élément sans savoir combien tu vas en avoir au final, pour peu que tu saches auquel tu en es :) Et le meilleur moyen pour ça, c'est de les compter ;)
$compteur = 0; // on va commencer à compter à partir de 0
while ( .... ) { // tant que j'ai des éléments

  if($compteur % 3 == 0) // je commence une nouvelle ligne
    ...

  ... // je vais mon p'tit bonhimme de code normalement

  if($compteur % 3 == 2) // je termine une ligne, 2 étant le dernier entier avant 3
    ...

  compteur++; // je compte un de plus sur mes petits doigts potelés ;)
}
Reste maintenant la possibilité que le nombre ne tombe pas juste pour finir ma ligne. Qu'à cela ne tienne.. je sais que j'ai eu $compteur élément, je sais que $compteur % 3 m'indique la colonne ou j'en suis, j'en déduis qu'il me reste ( 3 - ($compteur % 3) ) colonnes à remplir pour arriver au bout de ma ligne
if($compteur % 3 !=0) { // je suis au milieu d'une ligne
  for ($i = 0; $i < ( 3 - ($compteur % 3) ); $i++) 
    ... // je complete pour arriver au bout
}

Eléphant du PHP | 153 Messages

25 sept. 2006, 10:49

Je reviens vers vous :)

J'avais fait le test avec 3 colonnes, mais comme j'ai pas mal d'éléments à insérer, je suis obligé de passé à un rangement sur 2 colonnes.

Donc je me suis servi de ce topic

Biensûr, ça ne fonctionne pas :(
J'ai 10 résultats et cela ne m'en affiche que 5, alors que j'en ai bien 10 dans la source de la page et de cette manière :

Code : Tout sélectionner

<table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element1</td> <!-- visible --> <td>element2</td> <!-- visible --> </tr> </table> <tr> <td>element3</td> <!-- visible --> <td>&nbsp;</td> </tr> </table> <tr> <td>element4</td> <!-- visible --> <td>element5</td> <!-- visible --> </tr> </table> <tr> <td>element6</td> <!-- non visible --> <td>&nbsp;</td> </tr> </table> <tr> <td>element7</td> <!-- non visible --> <td>element8</td> <!-- non visible --> </tr> <tr> <td>element9</td> <!-- non visible --> <td>element10</td> <!-- non visible --> </tr> </table>
Code php :
echo "<table width="90%" border="0" cellspacing="0" cellpadding="0">"; 
   $q = "SELECT catID FROM categories WHERE parent = '$catID'"; 
   $r = mysql_query($q); 
   while ($row = mysql_fetch_array($r)) 
   { 
      $sql_prod = "SELECT nom FROM produits WHERE catID = '" .$row['catID']. "'"; 
      $result_prod = mysql_query($sql_prod); 
      $nb = mysql_num_rows($result_prod); 
      $compteur = 0; 
      while ($row = mysql_fetch_array($result_prod)) 
      {       
         if ($compteur % 2 == 0) 
         { 
            echo "<tr>"; 
         } 
         echo "<td>" .$row['nom']. "</td>"; 
                           
         if (($compteur + 1) % 2 == 0) 
         { 
            echo "</tr>"; 
         } 
         $compteur++; 
       } 
       if($nb % 2 == 0) 
       { 
          echo "</table>"; 
       } 
       else 
       { 
       $reste = ($nb % 2); 
       for($j = 0; $j < $reste; $j++) 
       { 
            echo "<td>&nbsp;</td>"; 
       } 
            echo "</tr>"; 
            echo "</table>"; 
       } 
   }
J'ai simplifié en insérant des echo au html, je les retirerai lorsque tout fonctionnera.

Merci pour votre aide :wink:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 sept. 2006, 11:07

Regarde le code source généré.. tu as une effroyable quantité de "</table>" pour fermer tes tableaux, et juste un seul "<table>" pour l'ouvrir.. faudrait déjà commencer par corriger ça :)

Eléphant du PHP | 153 Messages

25 sept. 2006, 12:11

Bien, bein ça va pas !
   $q = "SELECT catID FROM categories WHERE parent = '$catID'";  
   $r = mysql_query($q);  
   while ($row = mysql_fetch_array($r))  
   {
echo "<table width="90%" border="0" cellspacing="0" cellpadding="0">";  
      $sql_prod = "SELECT nom FROM produits WHERE catID = '" .$row['catID']. "'";  
      $result_prod = mysql_query($sql_prod);  
      $nb = mysql_num_rows($result_prod);  
      $compteur = 0;  
      while ($row = mysql_fetch_array($result_prod))  
      {
/* Si on est à la première de 2 photos, on crée la nouvelle ligne */         
         if ($compteur % 2 == 0)  
         {  
            echo "<tr>";  
         }  
         echo "<td>" .$row['nom']. "</td>";  
/* Si on est à la dernière d'une série de 2 photos, on ferme la ligne */                           
         if (($compteur + 1) % 2 == 0)  
         {  
            echo "</tr>";  
         }  
         $compteur++;  
       }
/* Si le nombre de photo est un multiple de 2, on ferme le tableau */  
       if($nb % 2 == 0)  
       {  
          echo "</table>";  
       }
/* Sinon, on comlpète avec des cellules vides avant de fermer le tableau */  
       else  
       {  
       $reste = ($nb % 2);  
       for($j = 0; $j < $reste; $j++)  
       {  
            echo "<td>&nbsp;</td>";  
       }  
            echo "</tr>";  
            echo "</table>";  
       }  
   }  
Resultat html (nombre d'éléments retournés = ok) :

Code : Tout sélectionner

<table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element1</td> <td>element2</td> </tr> </table> <table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element3</td> <td>&nbsp;</td> </tr> </table> <table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element4</td> <td>element5</td> </tr> </table> <table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element6</td> <td>&nbsp;</td> </tr> </table> <table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element7</td> <td>element8</td> </tr> <tr> <td>element9</td> <td>element10</td> </tr> </table>
Pour terminer, je donne ma langue au chat :lol:

Eléphant du PHP | 332 Messages

25 sept. 2006, 12:53

et si tu enlevais le echo echo </table> de ta boucle for ???

Eléphant du PHP | 153 Messages

25 sept. 2006, 13:24

ça ne change rien.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 sept. 2006, 14:06

Qu'est ce qui ne va pas ?

d'après le code que tu montres, on peut supposer que tu as :
- 2 éléments pour le premier idCat
- 1 élément pour le deuxième (complété d'un espace)
- 2 pour le troisième,
- 1 pour le quatrième (complété d'un espace)
- et 4 pour le dernier...

Le code correspond donc à priori bien à ce que tu souhaites, à savoir toutes tes données sur 2 colonnes :)

En revanche, le fait de faire un nouveau tableau à chaque fois (au lieu de juste faire une nouvelle ligne) fait que tes cellules ne seront pas alignées verticalement entre deux tableaux. Le navigateur va donc gérer la taille de celle-ci en fonction du contenu et si la première cellule contient du texte quand la seconde ne contient qu'un espace, elle sera beaucoup plus large.

Ajoute un width="50%" à tes <td> (puisqu'il y en a 2 par ligne), je pense que tu devrais obtenir l'effet désiré :)

Eléphant du PHP | 153 Messages

25 sept. 2006, 14:20

Bon, j'ai encore modifier le php
$q = "SELECT catID FROM categories WHERE parent = '$catID'";   
   $r = mysql_query($q);   
   while ($row = mysql_fetch_array($r))   
   { 
echo "<table width="90%" border="0" cellspacing="0" cellpadding="0">";   
      $sql_prod = "SELECT nom FROM produits WHERE catID = '" .$row['catID']. "'";   
      $result_prod = mysql_query($sql_prod);   
      $nb = mysql_num_rows($result_prod);   
      $compteur = 0;   
      while ($row = mysql_fetch_array($result_prod))   
      { 
/* Si on est à la première de 2 photos, on crée la nouvelle ligne */          
         if ($compteur % 2 == 0)   
         {   
            echo "<tr>";   
         }   
         echo "<td>" .$row['nom']. "</td>";   
/* Si on est à la dernière d'une série de 2 photos, on ferme la ligne */                            
         if (($compteur + 1) % 2 == 0)   
         {   
            echo "</tr>";   
         }   
         $compteur++;   
       } 
/* Sinon, on comlpète avec des cellules vides avant de fermer le tableau */   
       $reste = ($nb % 2);   
       for($j = 0; $j < $reste; $j++)   
       {   
            echo "<td>&nbsp;</td>"; 
            echo "</tr>";  
       }   
            echo "</tr>";   
            
          
   }
echo "</table>";   
Ce qui donne :

Code : Tout sélectionner

<table width="90%" border="0" cellspacing="0" cellpadding="0"> <tr> <td>element1</td> <td>element2</td> </tr> <tr> <td>element3</td> <td>&nbsp;</td> </tr> <tr> <td>element4</td> <td>element5</td> </tr> <tr> <td>element6</td> <td>&nbsp;</td> </tr> <tr> <td>element7</td> <td>element8</td> </tr> <tr> <td>element9</td> <td>element10</td> </tr> </table>
Je ne comprends pas pour quoi je me retrouve avec un "&nbsp;" à la 4ème et la 8ème colonne (que je ne veux pas) et pas la 12ème ?!

Eléphant du PHP | 153 Messages

25 sept. 2006, 15:34

Qu'est ce qui ne va pas ?

d'après le code que tu montres, on peut supposer que tu as :
- 2 éléments pour le premier idCat
- 1 élément pour le deuxième (complété d'un espace)
- 2 pour le troisième,
- 1 pour le quatrième (complété d'un espace)
- et 4 pour le dernier...

Le code correspond donc à priori bien à ce que tu souhaites, à savoir toutes tes données sur 2 colonnes :)
Ah ben voila d'où vient mon problème !!!!

Donc, comment faire pour ranger l'ensemble des éléments sur 2 colonnes ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 sept. 2006, 16:21

Tes &nbsp; en trop viennent du fait qu'il termine les lignes incomplètes avant de passer au prochain catID...

Sort la partie $reste et la boucle for() de ton while pour qu'il ne s'exécute qu'une fois que tu as lu tous tes éléments. Il ne devrait ainsi compléter que la dernière ligne :)

Sort également ton $compteur=0 de ton premier while, sans quoi à chaque $catID il reviendra à zéro, et à priori, ce qui t'interesse c'est qu'il te comptabilise tous les éléments quel que soit le $catID.

Enfin, dans ton calcul de $reste, ce n'est pas $nb qu'il te faut utiliser (qui ne comptabilise que le nombre de catID) mais le $compteur final qui t'indiquera combien d'éléments ont déjà été affiché :)

Eléphant du PHP | 153 Messages

25 sept. 2006, 16:30

Merci Ryle :D

Je ne croyais jamais y arriver, ça fonctionne très bien. Que j'ai un résultat pair ou impair.

Une chose, j'ai modifier $nb par $compteur, mais ça ne change rien à l'affichage, ça fonctionne bien avec les 2. Mais je vais rester avec $compteur, comme tu me l'as indiqué :wink:

Merci pour tout, franchement :merci:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 sept. 2006, 16:37

Y a pas de quoi :)

Pour le $reste, pour que ce soit cohérent, il faut que la valeur que tu testes soit égale au nombre total d'élément affiché (pour savoir combien de colonne ont été remplies et combien il faudrait éventuellement en rajouter)

Dans ton dernier code, $nb correspondait uniquement au nombre d'éléments de la dernière catégorie (affiche les deux, tu devrais voir la différence :)). Ca peu tomber juste mais ça n'a rien d'une certitude. En fait, il te faudrait cumuler les $nb de chaque catID pour obtenir le total.
C'est ce que tu fais en sortant le $compteur=0 de ta boucle, puisqu'il va s'incrémenter à chaque nouvelle cellule affichée, et ainsi au final te dire combien tu en avais :)