Boucle alphabet avec requête sql [Résolu]

Eléphant du PHP | 52 Messages

09 déc. 2011, 11:20

Bonjour,

Je souhaite réaliser un index rangé par ordre alphabétique avec comme intercalaire une lettre.
$requete = query("SELECT titre FROM table ORDER BY titre ASC", $db);
foreach(range('A','Z') as $i)
{
echo $i;
while($row = mysql_fetch_array($requete, MYSQL_ASSOC))
  {
 $titre= $row['titre']; 
 $prems = SUBSTR ($titre,0,1);

     if($prems == $i)
     {	 
      echo $row['titre'], "<br>\n";
      }
  }
}
Ce qui donne:

Code : Tout sélectionner

A Althéa Amandier Ancolie BCDEFGHIJKLMNOPQRSTUVWXYZ
La requête s’arrête après à la fin de la lettre A. A moins d'exécuter 26 fois la requête, je n'arrive pas à trouver la solution. Une petite idée ?
Modifié en dernier par nelumbo le 10 déc. 2011, 18:09, modifié 3 fois.

ViPHP
xTG
ViPHP | 7331 Messages

09 déc. 2011, 11:41

Ce n'est pas la requête qu'il faut modifier mais ton traitement d'affichage.
Il faut pouvoir combler les trous en affichant la lettre (et surtout ne pas devoir reparcourir le résultat de la requête pour chaque lettre...).

Exemple restreint (j'ai peut être pas suivi l'ordre alphabétique au sein des catégories mais on s'en fout, c'est le principe qui compte) :
// les lettres de l'alphabet (les catégories en gros)
$tabLettre = array('A', 'B', 'C', 'D', 'E', 'F');
// le tableau suivant simule les résultats de la requête
$tabInfos = array(
  0 => 'Amélie',
  1 => 'Arnaud',
  2 => 'Béatrice',
  3 => 'Delphine',
  4 => 'Eléanore'
);
$lettreAffiche = ''; // la dernière lettre affichée
// Equivalence de ta boucle while()
while( current($tabInfos) !== false ){
  $nom = current($tabInfos);
  // On affiche les catégories sautées
  while( $lettreAffiche != $nom[0] ){
    echo current($tabLettre) . '<br />'; // affichage de la lettre sautée
    $lettreAffiche = current($tabLettre); // on met à jour la dernière lettre affichée
    next($tabLettre);
  }
  echo $nom . '<br />';
  next($tabInfos);
}
// On fini d'afficher les lettres qui n'ont aucun nom
while( current($tabLettre) !== false ){
    echo current($tabLettre) . '<br />'; // affichage de la lettre sautée
    next($tabLettre);
}
Ce qui donnera :
A
Amélie
Arnaud
B
Béatrice
C
D
Delphine
E
Eléanore
F
Modifié en dernier par xTG le 09 déc. 2011, 14:29, modifié 2 fois.

Eléphant du PHP | 52 Messages

09 déc. 2011, 11:59

Le script ne fonctionne pas en local (wamp).

Code : Tout sélectionner

Notice: Undefined variable: lettreAffiche in C:\wamp\www\test.php on line 22 Amélie

ViPHP
xTG
ViPHP | 7331 Messages

09 déc. 2011, 12:07

J'ai corrigé cela, ainsi que d'autres trucs dans mon précédent message.
Je n'ai pas la possibilité de tester pour le moment, donc essayes de le comprendre et redis moi. ;)

Eléphant du PHP | 52 Messages

09 déc. 2011, 12:10

Merci, vais essayer de comprendre.

Résultat du script
A
Amélie
Arnaud
A
B
Béatrice
B
C
D
Delphine
D
E
Eléanore
E
F

ViPHP
xTG
ViPHP | 7331 Messages

09 déc. 2011, 14:30

Voilà le code a été épuré et corrigé.
N'hésites pas à poser des questions sur ce que tu ne comprends pas.

Eléphant du PHP | 52 Messages

09 déc. 2011, 19:32

Mon tableau avec un print_r($tab) s'affiche bien, mais dans le script ça va pas. Il me trouve 2 noms puis tourne.... en rond quoi :) .
$res= mysql_query("SELECT * FROM table", $db);
$tab = null;
while ($ligne = mysql_fetch_array($res)){ 
$tab [$ligne[0]] = "$ligne[8]" ; 
}
// les lettres de l'alphabet (les catégories en gros)
$tabLettre = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
$lettreAffiche = ''; // la dernière lettre affichée
// Equivalence de ta boucle while()
while( current($tab) !== false ){
  $nom = current($tab);
  // On affiche les catégories sautées
  while( $lettreAffiche != $nom[0] ){
    echo current($tabLettre) . '<br />'; // affichage de la lettre sautée
    $lettreAffiche = current($tabLettre); // on met à jour la dernière lettre affichée
    next($tabLettre);
  }
  echo $nom . '<br />';
  next($tab);
}
// On fini d'afficher les lettres qui n'ont aucun nom
while( current($tabLettre) !== false ){
    echo current($tabLettre) . '<br />'; // affichage de la lettre sautée
    next($tabLettre);
}

ViPHP
xTG
ViPHP | 7331 Messages

09 déc. 2011, 20:30

Je répond à côté de la plaque si j'insinue que tu ne trie pas les données par ordre alphabétique ?
$tab [$ligne[0]] = "$ligne[8]" ; 
Bon hormis le fait que les quotes sont monstrueuses... Ceci créé un tableau basé sur une clé, index 0 donc je suppose que c'est la clé primaire de la table.
Pour rappel tu peux ordonner les données via la clause ORDER BY en SQL.
Et tu peux demander à PHP de créer le tableau sans avoir à lui fournir les index :
$tab[] = $maDonnée;

Eléphant du PHP | 52 Messages

09 déc. 2011, 22:21

Ça marche impeccable :) Merci beaucoup
Bon hormis le fait que les quotes sont monstrueuses...
Tu peux m'en dire un peu plus ?

ViPHP
xTG
ViPHP | 7331 Messages

09 déc. 2011, 23:15

Tu demandes à PHP une double interprétation.
Quand tu utilises les doubles quotes cela spécifies une chaîne de caractère qui peut contenir des variables à interpréter.
Alors que tu peux tout simplement t'en passer.

Exemple :
echo "$var";
echo $var;

Eléphant du PHP | 52 Messages

09 déc. 2011, 23:34

hummmmm... et dans une requete mysql c'est pareil ?
mysql_query("SELECT id, titre FROM table WHERE valide='4' ORDER BY titre ASC", $db);
Je pourrait changer valide='4' en valide=4 . Ca fonctionne aussi mais il m'a semblé avoir lu que c’était le mal de pas les mettre dans ce cas.

Eléphant du PHP | 52 Messages

10 déc. 2011, 00:07

Bhein en fait la galère n'est pas fini ^^ . Le script plante si j'ai plus de 38 entrées.
LIMIT 0,37 ca fonctionne et LIMIT 0,38 fait une page blanche.
J'ai commenté la dernier partie du script car les lettres sans entrées s'affichent quand même.
$res= mysql_query("SELECT id, titre FROM table WHERE valide='4' ORDER BY titre ASC", $db);
$tab = null;
$tabId = null;
while ($ligne = mysql_fetch_array($res)){ 
$tab [] = $ligne['titre'];
$tabId [] = $ligne['id'];
}
$tabLettre = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');

$lettreAffiche = ''; // la dernière lettre affichée
// Equivalence de ta boucle while()
while( current($tab) !== false ){
  $nom = current($tab);
  $id = current($tabId);
  // On affiche les catégories sautées
  while( $lettreAffiche != $nom[0] ){
    echo "<div class=\"index\">".current($tabLettre) . "</div>"; // affichage de la lettre sautée
    $lettreAffiche = current($tabLettre); // on met à jour la dernière lettre affichée
    next($tabLettre);
  }  
  echo "<a href=\"".format($nom)."-".$id.".html\" title=\"$nom\">$nom </a><br />";
  next($tab);
  next($tabId);
}
/*On fini d'afficher les lettres qui n'ont aucun nom
while( current($tabLettre) !== false ){
    echo current($tabLettre) . '<br />'; // affichage de la lettre sautée
    next($tabLettre);
}
*/

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

10 déc. 2011, 01:56

Je pourrait changer valide='4' en valide=4 . Ca fonctionne aussi mais il m'a semblé avoir lu que c’était le mal de pas les mettre dans ce cas.
En SQL c'est pas tout à fait pareil. Les apostrophes servent à délimiter des chaines de caractères. Leur utilisation va donc dépendre du type de champ dans ta table :
- pour un champ de type char, varchar, text, date, ... qui sont des chaines de caractères, il faut obligatoirement les délimiter par des apostrophes
- pour un champ de type int, float, double, ... qui sont des nombres, il ne fau(drai)t jamais les délimiter par des apostrophes.

Pour ce qui est des nombres, MySQL tolère des apostrophes autour (c'est pas pour autant que c'est bien ;)). Et comme c'est probablement l'un des seuls, mieux vaut prendre l'habitude de bien faire et pas se soucier de la base de données :) (en tout cas pas sur ce point ;))
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 52 Messages

10 déc. 2011, 10:18

Pour ce qui est des nombres, MySQL tolère des apostrophes autour (c'est pas pour autant que c'est bien ;)). Et comme c'est probablement l'un des seuls, mieux vaut prendre l'habitude de bien faire et pas se soucier de la base de données :) (en tout cas pas sur ce point ;))
Merci, vais essayer d'en prendre l’habitude :D .

ViPHP
xTG
ViPHP | 7331 Messages

10 déc. 2011, 10:44

LIMIT 0,37 ca fonctionne et LIMIT 0,38 fait une page blanche.
C'est bizarre, car il n'y a pas de raison.
Fais un var_dump() de ton tableau récupéré.

Mais déjà si tu voulais avoir plus de sécurité il faudrait faire ceci :
$tab = array();
$tabId = array();
if( mysql_num_rows() > 0 )
while ($ligne = mysql_fetch_array($res)){
$tab [] = $ligne['titre'];
$tabId [] = $ligne['id'];
}
Initialiser à null les tableaux fait que si tu n'as pas de valeur le current() va travailler sur une variable qui n'est pas un tableau. Cette fonction n'est pas faite pour cela.
Faire un mysql_fetch_array() dans le cas d'une requête qui plante et qui ne retourne pas une ressource $res valide va te générer une erreur, on passe donc par mysql_num_rows() pour vérifier cela.