Suite au succès de l'article Créer un système de pagination et au nombre de demandes d'amélioration, je vous propose ici une fonction pagination qui vous permettra d'afficher facilement les liens vers les autres pages.
Le principal avantage de cette fonction est qu'elle n'affiche pas les liens vers toutes les pages mais les liens vers les premières, dernières et pages adjacentes à celle en cours.
Autre avantage non négligeable, ce code fonctionnera avec des Url Rewritée sans modification de votre part.
Nous supposons que vous savez comment récupérer les données de façon à les présenter sur plusieurs pages.
Si ce n'est pas le cas, je vous invite à consulter l'article Créer un système de pagination.
La fonction pagination()
function pagination($current_page, $nb_pages, $link='?page=%d', $around=3, $firstlast=1)
{
$pagination = '';
if ( !ereg('%d', $link) ) $link .= '%d';
if ( $nb_pages > 1 ) {
// Lien précédent
if ( $current_page > 1 )
$pagination .= '<a class="prevnext" href="'.sprintf($link, $current_page-1).'" title="Page précédente">« Précédent</a>';
else
$pagination .= '<span class="prevnext disabled">« Précédent</span>';
// Lien(s) début
for ( $i=1 ; $i<=$firstlast ; $i++ ) {
$pagination .= ' ';
$pagination .= ($current_page==$i) ? '<span class="current">'.$i.'</span>' : '<a href="'.sprintf($link, $i).'">'.$i.'</a>';
}
// ... après pages début ?
if ( ($current_page-$around) > $firstlast+1 )
$pagination .= ' …';
// On boucle autour de la page courante
$start = ($current_page-$around)>$firstlast ? $current_page-$around : $firstlast+1;
$end = ($current_page+$around)<=($nb_pages-$firstlast) ? $current_page+$around : $nb_pages-$firstlast;
for ( $i=$start ; $i<=$end ; $i++ ) {
$pagination .= ' ';
if ( $i==$current_page )
$pagination .= '<span class="current">'.$i.'</span>';
else
$pagination .= '<a href="'.sprintf($link, $i).'">'.$i.'</a>';
}
// ... avant page nb_pages ?
if ( ($current_page+$around) < $nb_pages-$firstlast )
$pagination .= ' …';
// Lien(s) fin
$start = $nb_pages-$firstlast+1;
if( $start <= $firstlast ) $start = $firstlast+1;
for ( $i=$start ; $i<=$nb_pages ; $i++ ) {
$pagination .= ' ';
$pagination .= ($current_page==$i) ? '<span class="current">'.$i.'</span>' : '<a href="'.sprintf($link, $i).'">'.$i.'</a>';
}
// Lien suivant
if ( $current_page < $nb_pages )
$pagination .= ' <a class="prevnext" href="'.sprintf($link, ($current_page+1)).'" title="Page suivante">Suivant »</a>';
else
$pagination .= ' <span class="prevnext disabled">Suivant »</span>';
}
return $pagination;
}
Explications
La fonction accepte 5 paramètres (mais seuls les 2 premiers sont obligatoires).
pagination($current_page, $nb_page, $link, $around, $firstlast);
- $current_page :
Le numéro de page actuelle - $nb_pages :
Le nombre total de page - $link :
Le 'href' du lien (il doit contenir %d qui sera remplacé par le numéro de page à l'aide la fonction sprintf), par défaut ?page=%d - $around :
Le nombre de liens à afficher juste avant et juste après la page courante : par défaut 3 - $firstlast :
Le nombre de liens à afficher au début et à la fin : par défaut 1
La fonction nous retourne la liste des liens sans paragraphe, il est conseillé de l'utiliser de cette manière :
echo '<p class="pagination">' . pagination(vos_parametres) . '</p>';
Design ?
En général, c'est plus beau avec du CSS.
C'est pour ça que je vous fournir un p'tit design de base, à vous de l'adapter à votre site 
.pagination {
line-height:2em;
}
.pagination a,
.pagination span {
padding:0.2em 0.5em;
}
.pagination a {
border:1px solid #9AAFE5;
color:#105CB6;
text-decoration:none;
}
.pagination a:hover {
border:1px solid #296BB5;
color:#000031;
}
.pagination .prevnext {
font-weight:bold;
}
.pagination span.disabled {
border:1px solid #DDDDDD;
color:#999999;
}
.pagination span.current {
border:1px solid #2E6AB1;
background-color:#2E6AB1;
color:#ffffff;
font-weight:bold;
}
Exemples
Des exemples d'utilisation sont disponible sur cette page.
Intégration
Si vous désirez intégrer cette fonction avec le code présenté dans l'article Créer un système de pagination, vous devez :
- Mettre à disposition la fonction pagination() (au début de la page ou dans un fichier externe que vous auriez inclus)
- Utiliser pagination() pour l'affichage des liens.
Ce qui donnera :
<?php
// Numero de page (1 par défaut)
if( isset($_GET['page']) && is_numeric($_GET['page']) )
$page = $_GET['page'];
else
$page = 1;
// Nombre d'info par page
$pagination = 10;
// Numéro du 1er enregistrement à lire
$limit_start = ($page - 1) * $pagination;
// Préparation de la requête
$sql = "SELECT * FROM table LIMIT $limit_start, $pagination";
// Requête SQL
$resultat = mysql_query($sql);
// Traitement et affichage des données
while ( $donnee = mysql_fetch_assoc($resultat) ) {
// ICI VOTRE CODE NORMAL
// Affichage d'un élément
}
// Nb d'enregistrement total
$nb_total = mysql_query('SELECT COUNT(*) AS nb_total FROM table');
$nb_total = mysql_fetch_array($nb_total);
$nb_total = $nb_total['nb_total'];
// Pagination
$nb_pages = ceil($nb_total / $pagination);
// Affichage
echo '<p class="pagination">' . pagination($page, $nb_pages) . '</p>';
?>


Super!
Merci beaucoup :-)
Hey cool, je me réjouit de tester tout ça
en tout cas bien cool ton blog continue !!!
Salut,
excuse moi, tu as barré quelques codes vers la fin du script final (echo...).
C'est volontaire ou pas ?
Salut gersay,
oui c'est volontaire et il ne faut pas en tenir compte.
Ceux qui utilisaient le code de l'article Créer un système de pagination doivent remplacer le code barré par :
echo '<p class="pagination">' . pagination($page, $nb_pages) . '</p>';
Nikel cette fonction !
mais c'est normal qu'on definit $currente_page dans la fonction et dans la page pour affiche la fonction tu mets $page ?
Salut
Je vous demande comment inverser la pagination de droite à gauche.
D'autre maniére je veux que les numéros s'affichent comme ca 3 2 1 et suivat et précident l'une prend la place de l'autre : suivat 3 2 1 précident.
Merci d'avance.
Salut hous,
pour inverser l'ordre, il te faudra inverser les différentes étapes de la fonction, ce qui donnera :
1) Lien suivant
2) Lien(s) fin
3) ... avant page nb_pages ?
4) On boucle autour de la page courante
5) ... après pages début ?
6) Lien(s) début
7) Lien précédent
De plus il faudra aussi inverser les différentes boucle for() :
// Lien(s) début
for ( $i=$firstlast ; $i>=1 ; $i-- ) {
// On boucle autour de la page courante
for ( $i=$end ; $i>=$start ; $i-- ) {
// Lien(s) fin
for ( $i=$nb_pages ; $i>=$start ; $i-- ) {
Je n'ai pas testé, il faudra peut-être faire quelques ajustements mais l'idée y est.
Bonne chance
Bonsoir Seebz,
.
Mon petit site a un peu évolué mais j'ai un petit problème avec ta fonction de pagination... étant donné que mon site fonctionne sur un principe relativement simple d'includes : une page identique pour tout le site et le contenu est inclu dedans et appelé via un GET.
J'obtiens donc des url dans ce style http://batteandroll.free.fr/index.php?page=blabla
Ton système de pagination fonctionne à la perfection sur la page d'accueil mais pour certaines autres pages ça se complique.
Lorsque un utilisateur souhaite changer de page via ta fonction de pagination sur une autre page du site que l'index on obtient un url du style
http://batteandroll.free.fr/index.php?nb=2
Cependant ma variable GET page disparait (normal), j'ai essayé de modifier ta fonction pour l'intégrer mais j'ai quelques problèmes.
J'ai essayé de t'expliquer mon problème de façon simple
Je vais continuer de réfléchir...
Merci d'avance!
Salut Dimitri,
tu peux fournir en troisième paramètre de la fonction le type d'url que la pagination doit générer.
Par exemple, pour 'index.php?page=videos' , il te suffit d'appeler la fonction pagination de cette façon :
pagination($current_page, $nb_page, 'index.php?page=videos&nb=%d');
%d sera remplacé par les numéros de page
Salut,
.
Que suis-je bête, je n'y avais même pas pensé!
Merci
Bonjour,
Tout d'abord merci pour ton tuto qui m'a vraiment beaucoup dépanné et...
désolé de te déranger pour quelque chose qui n'a rien avoir avec le sujet en cours
J'aurais voulus savoir comment mettre en place une zone de commentaire comme celle de ton site
Bien entendu pour tout ce qui est de la partie formulaire et enregistrement base de donnée c ok.
J'aurais plutôt voulut savoir comment tu procédais ensuite (après ta validation)
si tu avais quelque chose de plutôt automatisé, (en rapport avec la bbd) ou si tu mettais en forme chaque nouveaux message à la main, directement dans le code
Merci pour ton aide,
et tant qu'on y est meilleur voeux pour 2009!
Salut Virgile,
je te réciproque tes voeux
Concernant les commentaires, j'utilise htmlentities() et nl2br() au moment de l'enregistrement dans la DB.
Chaque commentaire est lié à un article par un champ (article_id) et pour les récupérer, je fais une requete du genre :
SELECT * FROM comments WHERE online=1 AND article_id='123' ORDER BY created_at
Voila, j'espère que ça t'aidera, si tu as encore une question, n'hésite pas à me contacter via le formulaire de contact
Salut seebz, j'ai copier votre dernier code mais il affiche un erreur dans cette ligne :
echo '<p class="pagination">' . pagination($page, $nb_pages) . '</p>';
Salut Abderrahmane,
c'est étrange car la fonction a déja été utilisée à maintes reprises
Quelle est l'erreur exacte ?
j'ai copier ton dernier code seulement et j'ai changé la table sql et quand j'affiche pour tester il affiche :
Fatal error: Call to undefined function pagination() in C:wampwwwtestzz.php on line 52
et la ligne 25 est :
echo '<p class="pagination">' . pagination($page, $nb_pages) . '</p>';
faut aussi copier la fonction pagination()
oui maintenant ça marche,
mais il y a un problème dans ces ligne :
// Préparation de la requête
$sql = "SELECT * FROM table ORDER BY id DESC LIMIT $limit_start, $pagination";
// Requête SQL
$resultat = mysql_query($sql);
// Traitement et affichage des données
while ( $donnee = mysql_fetch_assoc($resultat) )
{
echo $donnees['titre'];
}
il n'affiche rien.
le problème a été résolu merci de toute façon.
Bonjour,
je suis desolé si je te dérange, mais ou il faut mettre cette variable &genre='.$genre.'? car quand je l'a met dans $link ça marche pas.
@Abderrahmane : tu peux le spécifier en 3ème paramètre
pagination($page, $nb_pages, '?page=%d&genre=bidulle');
j'ai changé bidulle par $genre mais ça pas marcher
Hello,
je trouve qu'il manque un petit détail dans le script ; j'aimerais avoir un nombre constant de liens à l'affichage, mais cela n'est pas le cas quand on est dans les X ( = $showlast) premières (ou dernières) pages.
En effet, les X (= $around) liens qui ne précèdent pas le lien vers la page 1 (forcément hehe, on ne va pas aller en négatif) pourraient (enfin, devraient selon moi) être ajoutés aux X (= $around) liens qui le suivent.
Un exemple devrait $etre plus parlant (avec les valeurs par défaut):
admettons qu'on est à la page 1.
On a alors 0 lien avant le "1" (pas de page avec un nombre négatif, normal) et 3 liens après le "1" (je ne compte pas les liens firstLast); seulement 3 liens, alors qu'on pourrait (devrait) ajouter les 3 qu'on a pas mis avant le "1".
Cela permettrait d'avoir un nombre constant de liens affichés et serait encore plus propre.
Sinon ce script est chouette, merci.
bonjour,
je n'arrive pas a mettre un 3 ème parametre
$link='?admaction=editalbum&id_categorie='.$id_categorie'&page=%d'
Quand je remplace par une valeur numerique ca marche
$link='?admaction=editalbum&id_categorie=2&page=%d'
Ca doit etre une erreur d'ecriture de variable
d_categorie='.$id_categorie' j'ai essaye plusieurs truc mais rien ne va est ce que ca vient sprintf
Salut thomas, on dirait qu'il manque un point juste après $id_categorie
$link='?admaction=editalbum&id_categorie='.$id_categorie . '&page=%d'
Oui c'est une erreur dans mon poste j'avais bien le point.
erreur
Parse error: parse error in C:wampwwwxxxxincludeeditalbum.inc.php on line 68
ligne 68
function pagination($current_page, $nb_pages, $link="admin.php?admaction=editalbum&id_categorie='.$id_categorie.'&page=%d", $around=1, $firstlast=0)
et quand je remplace '.$id_categorie.' 2 ki correspond à une categorue de ma bdd ca fonctionne
id_categorie='.$id_categorie.' qui pose pb je vois pas pk
Okay, avec le code, je voit mieux les erreurs
Dans ta page php (ou dans un fichier inclus) tu place la fonction qui provient de cet article sans la modifier.
Tu dois aussi adapter le code de la partie "intégration" selon tes besoins.
Ensuite, à l'endroit où tu veux afficher les liens, tu dois APPELER la fonction de cette manière (attention à ne pas mélanger doubles et simple guillemets) :
echo pagination($current_page, $nb_pages, 'admin.php?admaction=editalbum&id_categorie='.$id_categorie.'&page=%d', 1, 0);
Merci seebz pour ton coup de main ça fonctionne, j'avais po tout comrpis ...
Bonjours,
, pourrez tu m'aider s'il te plaît seebz ?
J'ai suivi ce petit tuto très intéressant et je l'ai appliquer ensuite, mais sa afficher plus les messages postez dans mon livre d'or
PS : Aide par e-mail ou msn lien de mon livre d'or : http://initialdfr.free.fr/livre-dor/
Bonjour!
Je souhaiterais apporter une modification au code, actuellement quand on remplace le numéro de la page en cours par le numéro d'une page qui n'existe pas (parce que trop grand) on arrive sur une page vide.
Comment faire pour que cela fasse comme sur ton blog et qu'on soit redirigé vers la dernière page ?
Merci !
@Dragonblack95:
tu dois t'assurer de bien utiliser "$donnee" dans la partie "affichage d'un élément" (ou adapter le nom de la variable dans le while)
// Traitement et affichage des données
while ( $donnee = mysql_fetch_assoc($resultat) )
@Guillaume:
tu dois calculer le nombre de pages ($nb_pages) au début du code et faire une condition du type
if( $_GET['page']>$nb_pages )
{
// Redirection (on ne doit pas avoir utilisé "echo()" avant)
header('Location: ?page='.$nb_pages);
}
Yeah impeccable
Merci bien!
Salut,
Merci sa marche mais j'ai une autres question, les messages sont classé du plus ancien au plus récent peut-on faire l'inverse ?
Merci d'avance !
Un bug se produit quand par exemple on donne 40 pour le nombre de pagination et il y a moins de 40 infos dans le résultat de la requête il y aura rien d'afficher...
je fais comme ça :
<?php
// Affichage des liens de pagination
echo '<p class="pagination">'.pagination($page, $nb_pages, $link='index.php?p=liste_evenements&page=%d').'</p>';
?>
Merci !
Salut Augustin, on parle de ton problème dans les commentaires 29 et 30
oh merci c'est parfait c'est le meuilleur tuto
sur la pagination
Bonjour,
quant on est à la version php 5.3.0. on a une erreur :
if ( !ereg('%d', $link) ) $link .= '%d';
Comment y remédier merci
En effet, ereg() est déprécié, il faut utiliser preg_match() :
if ( !preg_match('`%d`', $link) ) $link .= '%d';
Merci excellent tuto ça m'a bien aidé !
Je mettrais un p'tit lien en l'honneur de ton article génial sur mon site
Bonjour Seebz,
Concernant cette requête SQL des commentaires:
SELECT * FROM comments WHERE online=1 AND article_id='123' ORDER BY created_at
CREATE TABLE `comments` (
`article_id` smallint(10) unsigned NOT NULL auto_increment,
`online` tinyint(1) NOT NULL default '0',
`contenu` text NOT NULL,
`created_at` char(10) NOT NULL default '1261717058',
PRIMARY KEY (`article_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Je souhaiterais me conformer à votre TABLE MySQL originale et donc comment vous organisez le contenu de votre TABLE MySQL ?
Je suis en train d'améliorer mon page des news.
Merci d'avance, Theo.
Salut Theo,
voici un structure de table que j'utilise pour un site :
CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`article_id` int(11) NOT NULL DEFAULT '0',
`author` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`email` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`site` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`message` text COLLATE utf8_unicode_ci NOT NULL,
`online` tinyint(1) NOT NULL DEFAULT '0',
`created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `article_id` (`article_id`),
KEY `online` (`online`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Bonsoir,
Merci pour cet excellent script de pagination ! J'en cherchais un sur le Site du Zéro pour mon Server Status Checker ( http://www.flogiweb.biz/status/ ).
bonjour,
bonjour et merci pour ce script.
pourriez vous m'aider s'il vous plait ?
Cela fait maintenant 3 jours que j'essaie d'installer votre script. Tout fonctionne sauf un paramétre :
Lorsque je fais ma première sélection tout fonctionne normalement : à savoir que le nombre de résultat est juste, le nombre de page correspondant aussi.
Cependant, lorsque je désire changer de page, l'affichage reprend l'ensemble de ma base de donnée et donc le nombre de résultat n'est plus juste, et des pages sont rajoutées.
Exemple : j'effectue une recherche ou il devrait y avoir 7 réponses dans ma base de donnée. Je sélectionne 3 réponses par page. Je devrai donc obtenir une réponse de 3 pages.
Jusque là tout va bien. Mais lorsque je clique sur la page 2 ou la page 3, ou sur le bouton suivant, un nombre de page correspondant au total des id de ma base de donnée divisé par 3.
Que puis je faire pour rectifier tout cela ?
Merci de m'aider car je débute en php.
Pascal