J'ai été confronté tout à l'heure à un problème simple, mais qui peut poser problème : On vous demande de lister les éléments d'une table MySQL sur une page, et d'en faire une pagination. Tout ce qu'il y a de plus normal. Pour faire ça, vous allez jouer sur les LIMIT de votre requète.
Exemple :
SELECT * FROM utilisateur LIMIT 20,10
Où on afficherai la seconde page des utilisateurs, avec 10 affichages.
Maintenant, imagninez qu'on veuille trier cette requête selon les nom des utilisateurs. Il suffirait de faire :
SELECT * FROM utilisateur LIMIT 20,10 ORDER BY nom ASC
Bon, jusque là, pas de problème particulier.
Maintenant vous ne voulez pas un affichage trié par nom, mais aléatoire. Intuitivement, on ferait simplement :
SELECT * FROM utilisateur LIMIT 20,10 ORDER BY RAND()
Ce qui n'est pas totalement faux. Le problème avec cette solution, c'est que lorsque vous allez changer de page, le tri va changer, et il sera donc impossible aux visiteurs d'afficher tous les noms, ce sera complètement cahotique.
La solution consiste à générer un nombre aléatoire en PHP, à l'enregistrer en session, et à le passer à la requête MySQL, dans les parenthèses du RAND, et le tour est joué. Ainsi le nombre alétoire généré sera toujours le même pour la session en cours, et on se retrouver avec le même tri sur toutes les pages.
Le code pour générer et enregistrer le nombre aléatoire en PHP :
$rand = $_SESSION['rand'];
if (empty($rand)) {
srand((float)microtime()*1000000);
$rand = "0.".rand();
$_SESSION['rand'] = $rand;
}
Bien sûr, il faudra que la session soit démarrer avec session_start() plus haut et qu'aucun header n'ai déjà été envoyé (ou bien utiliser ob_start())
Enfin, la requête MySQL devient :
SELECT * FROM utilisateur LIMIT 20,10 ORDER BY RAND($rand)
Et voilà, vous avez une belle pagination avec un tri aléatoire.
Commentaires.
#1 par matthieu
Imagine des var de session dans les Proc Stock ! Je sais je suis fou.
le Jeudi 12 Avril 2007 à 22:16:01
#2 par Materazzi
Thx pour ton article, je pense que ça aidera beaucoup de monde, et moi aussi j'avais jamais pensé à faire ça.
@++
le Mercredi 23 Mai 2007 à 00:01:43
#3 par tapi
Génial, voilà des semaines que je cherchais cette procédure.
Merci
le Mardi 11 Mars 2008 à 16:35:44
#4 par nicko
fonctionne pas :(
le Mercredi 21 Mai 2008 à 17:28:03
#5 par Gilles
Petite correction, d'après la doc MySQL5, RAND(N) prend un entier en paramètre. Sinon c'est cool.
le Jeudi 24 Juillet 2008 à 15:19:00
#6 par Oliwood
Hello !
Merci bien, je cherchais quelque chose de similaire depuis pas mal de temps :-)
Mais maintenant, étant donné qu'il y a une session d'ouverte, si j'affiche la page avec cette pagination, puis je me balade sur le site (je regarde d'autres pages) puis je reviens sur la pagination, il m'affiche à nouveau le même résultat que précédemment... (normal vu qu'il y a une session) est-ce qu'il y a moyen d'améliorer ça ?
MErci
A+
le Dimanche 09 Mai 2010 à 19:01:47
#7 par Nyro
Pour résoudre ce problème, il existe 3 solutions selon moi :
1) ajouter 1 autre variable de session avec le timestamp courant. Quand on revient sur la page, on regarde si ce timestamp n'est pas trop vieux. Si c'est le cas, on génère 1 nouveau random, sinon on utilise celui de session
2) sur toutes les autres pages autres que celle de la pagination, on supprime la variable de session
3) sur la page de pagination, on génère 1 new random si :
- on est sur la page 1
- la page précédente n'est pas une page de random (on le sait grâce à $_SERVER['HTTP_REFERER'])
à tester en cas réel bien sûr ;)
le Dimanche 09 Mai 2010 à 19:35:22
#8 par Oliwood
Merci pour la réponse rapide et les différentes pistes !
J'ai retenu la 3ème, à la différence que je ne génère pas un nouveau random si page = 1 (si je passe en revue toute la pagination du site et que finalement je me souviens qu'à la page 1 il y a un truc qui m'intéresse, lorsque je reviens sur 1, il génère une nouvelle pagination !)
C'est donc si page = inexistant que je génère un nouveau random... du-coup il créé 2 random coup sur coup, c'est sûrement un peu crade, mais ça a l'air de bien fonctionner :-)
Merci
A+
le Dimanche 09 Mai 2010 à 20:26:51
Ajouter un commentaire.