web 2.0

Seebz.net

Créer un système de pagination

La pagination (afficher des informations sur plusieurs pages) permet de faciliter la navigation et d'économiser les ressources systèmes.
Nous allons voir ici comment faire un système de pagination facilement.

Mais quelle est vraiment l'utilité d'un tel système ?Imaginons que vous avez une page qui liste des informations récupérées de la Base de Données (c'est le cas des pages blog et liens sur Seebz.be).

Lorsque la liste est courte, il n'y a pas de problème: les informations sont facilement accessibles et les requêtes ne sont pas lourdes pour le système.

Mais où cela devient un problème, c'est lorsque la liste commence à devenir plus longue, le visiteur se retrouve alors face à pleins d'information et il lui est difficile de retrouver ce qu'il cherche.
De même, le système peut surcharger car il doit gérer plein d'enregistrement d'un coup.

Votre code (sans pagination)

Le code source de votre page ressemble grossièrement à ceci :

<?php

// Requête SQL
$sql = 'SELECT * FROM table';
$resultat = mysql_query($sql);

// Traitement et affichage des données
while ( $donnee = mysql_fetch_assoc($resultat) ) {
	echo $donnee['champ'];
}

?>

Les modifications à faire

Afin de créer notre système de pagination, nous avons besoin :

- du nombre d'informations qui seront affichées par page,
Nous appellerons cette variable $pagination et elle aura toujours la même valeur (10 dans l'exemple).

- du numéro de la page en cours,
Ce paramètre sera donné via l'URL (par exemple index.php?page=2)

- connaître le nombre total d'informations contenues dans la base de données,
Une requête SQL nous aidera à y parvenir

- de modifier notre requête SQL ,
Afin de ne récupérer que les 10 informations demandées (à l'aide de la commande LIMIT)

- de créer le code (x)html,
Les liens vers les autres pages
Edit : Vu le succès de cet article et les nombreuses demandes d'amélioration, je vous invite à consulter l'article Pagination 2, comme avant ... en mieux pour un plus bel affichage de la liste des liens.

On commence

Nous allons commencer par récupérer le numéro de la page en cours.
Pour rappel, ce paramètre vient de l'URL ( index.php?page=X ) :

// Numero de page (1 par défaut)
if( isset($_GET['page']) && is_numeric($_GET['page']) )
	$page = $_GET['page'];
else
	$page = 1;

Ensuite, nous devons préparer notre requête SQL.
Nous devons donc calculer à partir de quel id récupérer les informations :

// Nombre d'infos 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";

Si vous ne comprenez pas la clause LIMIT, je vous conseille de vous documenter sur le site de MySQL.Vient ensuite le code normal de la page (celui qui avait avant, sans pagination, excepté la commande SQL) :

// Requête SQL
$resultat = mysql_query($sql);

// Traitement et affichage des données
while ( $donnee = mysql_fetch_assoc($resultat) ) {
	echo $donnee['champ'];
}

Nous avons besoin de compter le nombre d'enregistrements contenus dans la BD.

// 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'];

Nous pouvons maintenant écrire le système de pagination (les liens des autres pages) :

// Pagination
$nb_pages = ceil($nb_total / $pagination);

echo '<p>[ Page :';
// Boucle sur les pages
for ($i = 1 ; $i <= $nb_pages ; $i++) {
	if ($i == $page )
		echo " $i";
	else
		echo " <a href=\"?page=$i\">$i</a> ";
}
echo ' ]</p>';

Et voilà

Vous avez maintenant un beau système de pagination tel que celui sur Seebz.net.

Vous pouvez bien entendu l'adapter car il est assez simpliste. J'ai du volontairement omettre certaines explications vu la longueur de l'article mais je suis sur que vous n'aurez pas de mal à comprendre le principe de ce code.

Un petit résumé pour vous faciliter le copier-coller ;;)

<?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);

echo '<p>[ Page :';
// Boucle sur les pages
for ($i = 1 ; $i <= $nb_pages ; $i++) {
	if ($i == $page )
		echo " $i";
	else
		echo " <a href=\"?page=$i\">$i</a> ";
}
echo ' ]</p>';

?>

J'admets que cet article est (un peu) long mais c'est aussi ça les joies de la programmation :p
Suite au prochain numéro

Partager : Share
 

20 Réponses à “Créer un système de pagination”

  1. Superbe article :D
    Ça va beaucoup me servir car je me retrouvais plus avec toutes mes données en une seule page !
    Maintenant ,je peux afficher un certain nombre par page ! Ouais !!!!!!! xD

  2. Bon article mais j'ajoute quelques points d'optimisation :

    1/ Pas de SELECT * mais listage des champs à récupérer même si l'on récupère tout.
    2/ Utiliser mysql_fetch_assoc() à la place de mysql_fetch_array() car beaucoup plus rapide
    3/ Dans les echo(), utiliser les apostrophes pour les chaînes statiques et séparer les variables des chaînes de caractères avec la virgule.

  3. Salut Emacs,
    content de te voir ici ;)

    1/ difficile ici de détailler des champs que je ne connais pas, les champs en question ne font pas l'objet de mon article.
    2/ je n'ai jamais réellement fait la comparaison, j'en prend note.
    3/ je sais mais encore une fois, j'ai préféré une meilleur lisibilité à l'optimisation (mes articles sont avant tout 'pédagogiques').

    Mais un prochain article sur l'optimisation du code est fort probable.

  4. Salut ^^

    Je vais expliquer la différence entre mysql_fetch_array() et mysql_fetch_assoc(). Pourquoi est-il préférable d'utiliser la seconde fonction ? Tout simplement parceque mysql_fetch_array() génère deux tableaux identiques (donc duplication des données). L'un est associatif et l'autre indexé numériquement.

    Admettons que j'ai le code suivant :

    <?php

    // Connexion à la bdd
    ...

    $req = mysql_query('SELECT nom, prenom, email FROM membre WHERE membre_id = 3');
    $membre = mysql_fetch_array($req);

    ?>

    Et bien si je veux afficher le nom du membre, j'ai le choix entre :

    <?php echo $membre[0]; ?>

    Ou

    <?php echo $membre['nom']; ?>

    Il y'a donc bien duplication des informations ! C'est pourquoi il est recommandé de faire le choix dès le début du tableau que l'on veut récupérer. Personnellement je préfère l'associatif car il facilite la maintenance du code. Donc au final j'utilise mysql_fetch_assoc(). Si l'on souhaite récupérer les infos dans un tableau à clés numériques, alors on préfèrera mysql_fetch_row().

    Voilà pour le petit bilan optimisation :)

    ++

    Hugo.

  5. merci pour cet article qui fonctionne pesque bien. En effet, j'ai des problèmes au niveau de la pagination.

    ma première page s'affiche bien, mais lorsque je clique sur 2, pour accéder à la deuxième page, rien ne s'affiche...

    ai-je besoin de créer une deuxième page pour afficher le reste de mes données ?

    merci d'avance pour votre aide

  6. Salut bedoc, pour ton problème, tu ne dois pas créer de nouvelles pages (sinon notre système n'a aucune utilité).

    Je pense que ton problème est au niveau du lien, essaye :
    echo " <a href="{$_SERVER[PHP_SELF]}?page={$i}">$i</a> ";

    a+ ;)

  7. Merci bcp, j'ai réussi et ça faisait un moment que je galerais.
    Merci

  8. Bonjour, j'ai un petit problème en ce qui concerne la ligne echo "<a href="?page=$i">"$i"</a>";

    J'obtiens le message d'erreur suivant : Parse error: parse error, unexpected '=' in C:\Program Files\EasyPHP 2.0b1\www\news.php on line 106

    Que puis-je faire ?

  9. Tu as raison kelbo, il semblerait qu'il y a eu un petit problème quand je suis passé à la version 2 du site.

    En fait, il faut échapper les guillemets :

    echo " <a href=\"?page=$i\">$i</a> ";

  10. Merci, si j'étais plus doué, ça fonctionnerait ^^
    Il me reste un problème au niveau de l'affichage,je voulais faire apparaitre 5 articles par page, néanmoins sur chaque page j'affiche 5 fois les 5 derniers articles, j'ai beau chercher je ne trouve pas de solution à mon code, si quelqu'un pouvait m'aider ce serait vraiment me faciliter tout ça ^^


    /* Traitement et affichage des données */
    while ( $donnee = mysql_fetch_array($resultat) ) {

    /* ICI VOTRE CODE NORMAL */
    // On récupère les 5 dernières news
    $retour = mysql_query('SELECT * FROM news ORDER BY id DESC LIMIT 0, 5');
    while ($donnees = mysql_fetch_array($retour))
    {
    ?>
    <div class="news">
    <h3>
    <em>News du <?php echo date('d/m/Y', $donnees['timestamp']); ?></em>
                    -
                    <?php echo $donnees['titre']; ?>
    </h3>

    <p>
    <?php
    // On enlève les éventuels antislash PUIS on crée les entrées en HTML ()
    $contenu = nl2br(stripslashes($donnees['contenu']));
    echo $contenu;
    ?>
    </p>
    </div>
    <?php
    } // Fin de la boucle des news

    // FIN DU CODE NORMAL
    }

  11. En fait, la partie 'ICI VOTRE CODE NORMAL' ne doit plus contenir de requete SQL, ni de boucle car ça a été fait plus haut.

    Il faut mettre dans cette partie uniquement l'affichage d'une news qui est disponible dans le tableau $donnee.

    Donc dans ton cas :

    /* Traitement et affichage des données */
    while ( $donnee = mysql_fetch_array($resultat) ) {

            // ICI VOTRE CODE NORMAL
            // ou plutot : ici l'affichage d'une news

    ?>
    <div class="news">
    <h3>
            <em>News du <?php echo date('d/m/Y', $donnee['timestamp']); ?></em>
            -
            <?php echo $donnee['titre']; ?>
    </h3>

    <p>
    <?php
            // On enlève les éventuels antislash PUIS on crée les entrées en HTML ()
            $contenu = nl2br(stripslashes($donnee['contenu']));
            echo $contenu;
    ?>
    </p>
    </div>
    <?php

            // FIN DU CODE NORMAL
            // (fin de l'affichage d'une news)

    }

  12. Ca fonctionne, merci beaucoup :)

  13. Je ne sais pas si ça servira à quelqu'un mais je le poste quand même.

    Si vous désirez afficher en dessous de votre pagination de quoi passer directement à la page suivante où la page précédente voici le code nécessaire à introduire en dernier dans votre code :

    <?
    if ($page > 1)
                    echo " <a href=\"?page=".($page-1)."\">Précédent</a> ";
            else
                    echo "Précédent";
                   
            if ($page < $nb_pages)
                    echo " <a href=\"?page=".($page+1)."\">Suivant</a> ";
            else
                    echo "Suivant";
    ?>

  14. Bonjour,

    Merci pour ce code qui est exactement ce que je cherchais :-).

    J'aimerais cependant savoir s'il est possible de le modifier un peu. Je voudrais, lorsque j'ai 10 pages par exemple, afficher uniquement les 3 dernière et les 3 premières (un peu à la phpBB) et remplacer le milieu par des "...".

    Peux-tu m'aider ?

    Merci!

  15. Merci beaucoup, bon script, simple et efficace ;)

  16. merci mec, je me suis bien inspiré de ton code... je n'arrivait pas a faire en sorte que la page sélectionné soit non "clickable"

    merci

  17. Bonjour;

    Merci beaucoup pour ce script qui a du etre util à plein de monde :)

  18. salut
    moi ce que je veut c'est decouper ce code en fonction puisqu'il se repete sur plusieur pages por mon application web et je veut pas alourdir mes script
    je veut diviser mais je ne sais pas comment y proceder
    merci pour l'aide

  19. Bonjour Seebz,

    Merci d'avoir posté aussi rapidement à ma réponse.

    Je travaille actuellement sur mes CMS des News cela m'a permis de bien avancer dans mes scripts PHP.

    Tous mes voeux de Nouvel An 2010 avec pleines de bonnes résolutions bien à la famille qu'à vos projets en Web 2.0

    Cordialement, Theo alias (TLN0.free.fr)

  20. Bonsoir,

    j'ai le même problème que l'un d'entre vous, ma pagination affiche le contenu de ma première page, et il reconnait le nombre de page en fonction du volume d'affichage mais les autres pages sont vides. Pourtant j'ai fais le changement
    comme écrit dans les commentaires ci-dessus.

    Ce qui est louche aussi c'est qu'il m'affiche que les 2 premieres sorties de ma base sur ma premiere page même si je met l'affichage à 3.

Poster un commentaire

Remonter