Tutoriel - Faire une pagination

WhiiTe'

Administateur
Ancien staff
Inscription
22 Octobre 2011
Messages
14 704
Réactions
8 499
Points
32 425
:induste: Faire une pagination :induste:

Bonjour Induste,

Dans ce tutoriel on va voir comment faire une pagination, je vais vous montrer deux façons, l'une avec un tableau, et l'autre via une base de données.
Vous devrez en fonction de la partie que vous suivrez avoir le fichier Json ou importer le fichier SQL qui se trouvent dans le fichier zippé.

Sommaire :
  1. Faire une pagination - Avec un tableau
  2. Faire une pagination - Depuis la base de données
  3. Affichage des données
Pour la troisième partie, le code est adapté aux deux parties précédentes, donc peu importe ce que vous choisirez, ça fonctionnera.
Vous trouverez aussi dans le dossier du projet zippé les fichiers de code attaché au sujet. pour les feignasses quoi

:induste: Faire une pagination - Avec un tableau :induste:

Placez le fichier Json où vous le souhaitez dans votre projet.

On va commencer par créer un nouveau fichier PHP, index.php pour ma part.

Ensuite, on va récupérer le contenu du fichier Json et le décoder.

PHP:
<?php

$items = file_get_contents('items.json');
$items = json_decode($items, true);

Dans la variable $items se trouve donc un tableau à 200 entrées.
On va ensuite définir la page sur laquelle on se trouve, par défaut on sera sur la première page.

PHP:
$page = (!empty($_GET['page']) && $_GET['page'] > 0) ? intval($_GET['page']) : 1;

Ensuite on va définir le nombre de lignes à afficher par page, et récupérer le total de page qu'on aura.

PHP:
$limit = 20;
$totalPages = ceil(count($items) / $limit);

La variable $totalPages contiendra le nombre de pages qu'on aura en tout, dans notre cas pour 200 entrées dont 20 par page, on aura 10 pages au total.

Ensuite on va en quelque sorte "sécuriser" notre pagination pour pas que quelqu'un change l'URL, mette la page 20 alors que le maximum est 10.

PHP:
$page = max($page, 1);
$page = min($page, $totalPages);

Sachant que la variable $page contient la page actuelle, on lui indique que le minimum est 1 et que le maximum est la variable $totalPages.
Maintenant si on met 8987 dans l'URL alors que la page maximale est 50, on verra les données de la page 50.

Plus d'infos sur ces fonctions :
Ensuite, nous allons couper notre tableau, pour récupérer uniquement les valeurs de la page qu'on visionne.

PHP:
$offset = ($page - 1) * $limit;
$offset = ($offset < 0) ? 0 : $offset;
$items = array_slice($items, $offset, $limit);

La variable $offset contient un entier qui indique à quel endroit commencer à lire le tableau.
Exemple : Sur la page 10, on affiche les éléments 180 à 200 car la limite par page est 20, il faut donc couper le tableau de 0 à 180, pour garder que les 20 éléments suivants.

Grâce à la fonction array_slice, on coupe notre tableau sans difficulté.


Et voilà, nous avons notre tableau de 200 entrées qui est désormais coupé en 20.
Avant de passer à l'affichage, on va voir comment faire une pagination depuis la base de données.

:induste: Faire une pagination - Depuis la base de données :induste:

Pour cette seconde partie du tutoriel, il vous faudra avoir rempli votre base de données.
On va repartir sur un fichier vierge que je nommerai index_db.php.

On va ensuite lier la base de données.

PHP:
$pdo = new PDO('mysql:host=db_host;dbname=db_name', 'db_user', 'db_pass');

Vous constaterez qu'il y a peu de différences entre la première partie du tutoriel, et la seconde.
On définit la page qu'on visionne, la limite de lignes à afficher par page.

PHP:
$page = (!empty($_GET['page']) && $_GET['page'] > 0) ? intval($_GET['page']) : 1;
$limit = 20;

Ensuite il faut qu'on récupère le total d'entrée dans la base de données, pour déterminer le nombre de pages qu'on aura au total.

PHP:
$totalItems = $pdo->query('SELECT count(id) AS total FROM items')->fetch(PDO::FETCH_ASSOC)['total'];
$totalPages = ceil($totalItems / $limit);

Comme sur la première partie, on "sécurise" notre variable $page, et on récupère l'offset.
PHP:
$page = max($page, 1);
$page = min($page, $totalPages);

$offset = ($page - 1) * $limit;
$offset = ($offset < 0) ? 0 : $offset;

Pour conclure, il faut récupérer tous nos items qui sont dans la base de données, en précisant où commencer et la limite.
PHP:
$items = $pdo->query('SELECT * FROM items ORDER BY id ASC LIMIT '. $offset . ',' . $limit);

C'est tout pour cette seconde partie du tutoriel.

:induste: Affichage des données :induste:

Comme je vous l'ai précisé plus haut, le code que je vous donne ci-dessous fonctionne pour les deux parties, il vous faudra juste faire attention au nom des variables.

HTML:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Paginate</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <table class="table table-hover table-bordered">
        <tr>
            <th>ID</th>
            <th>UserId</th>
            <th>Title</th>
        </tr>
        <?php foreach ($items as $item): ?>
            <tr>
                <td><?= $item['id']; ?></td>
                <td><?= $item['user_id']; ?></td>
                <td><?= $item['title']; ?></td>
            </tr>
        <?php endforeach; ?>
    </table>

    <nav aria-label="Array pagination">
        <ul class="pagination">
            <?php if($page != 1){ ?>
                <li class="page-item">
                    <a class="page-link" href="index.php?page=<?= $page - 1; ?>" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                        <span class="sr-only">Previous</span>
                    </a>
                </li>
            <?php } ?>
            <?php for($i = 1;$i <= $totalPages;$i++) {?>
                <li class="page-item <?= ($i == $page) ? 'active' : ''; ?>"><a class="page-link" href="index.php?page=<?= $i; ?>"><?= $i; ?></a></li>
            <?php } ?>
            <?php if($page < $totalPages){ ?>
                <li class="page-item">
                    <a class="page-link"href="index.php?page=<?= $page + 1; ?>" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                        <span class="sr-only">Next</span>
                    </a>
                </li>
            <?php } ?>
        </ul>
    </nav>
</div>
</body>
</html>

Vous constaterez que j'ai intégré bootstrap, ce n'est qu'une question de design, vous pouvez faire sans ou intégrer un autre framework CSS.

C'est tout pour cette troisième partie concernant l'affichage, je ne m'attarde pas sur ce sujet car j'estime qu'il est relativement simple de manipuler ce code pour l'adapter à vos besoins.

Si vous avez des suggestions d'améliorations, ou des idées d'autres tutoriels à faire, n'hésitez pas à me demander !

:induste: WhiiTe' :induste:
 

Fichiers joints

  • items.zip
    9.2 KB · Affichages: 7

Enzo34!

★REALITYGAMING★
Premium
Inscription
31 Janvier 2014
Messages
1 417
Réactions
329
Points
17 831
:induste: Faire une pagination :induste:

Bonjour Induste,

Dans ce tutoriel on va voir comment faire une pagination, je vais vous montrer deux façons, l'une avec un tableau, et l'autre via une base de données.
Vous devrez en fonction de la partie que vous suivrez avoir le fichier Json ou importer le fichier SQL qui se trouvent dans le fichier zippé.

Sommaire :
  1. Faire une pagination - Avec un tableau
  2. Faire une pagination - Depuis la base de données
  3. Affichage des données
Pour la troisième partie, le code est adapté aux deux parties précédentes, donc peu importe ce que vous choisirez, ça fonctionnera.
Vous trouverez aussi dans le dossier du projet zippé les fichiers de code attaché au sujet. pour les feignasses quoi

:induste: Faire une pagination - Avec un tableau :induste:

Placez le fichier Json où vous le souhaitez dans votre projet.

On va commencer par créer un nouveau fichier PHP, index.php pour ma part.

Ensuite, on va récupérer le contenu du fichier Json et le décoder.

PHP:
<?php

$items = file_get_contents('items.json');
$items = json_decode($items, true);

Dans la variable $items se trouve donc un tableau à 200 entrées.
On va ensuite définir la page sur laquelle on se trouve, par défaut on sera sur la première page.

PHP:
$page = (!empty($_GET['page']) && $_GET['page'] > 0) ? intval($_GET['page']) : 1;

Ensuite on va définir le nombre de lignes à afficher par page, et récupérer le total de page qu'on aura.

PHP:
$limit = 20;
$totalPages = ceil(count($items) / $limit);

La variable $totalPages contiendra le nombre de pages qu'on aura en tout, dans notre cas pour 200 entrées dont 20 par page, on aura 10 pages au total.

Ensuite on va en quelque sorte "sécuriser" notre pagination pour pas que quelqu'un change l'URL, mette la page 20 alors que le maximum est 10.

PHP:
$page = max($page, 1);
$page = min($page, $totalPages);

Sachant que la variable $page contient la page actuelle, on lui indique que le minimum est 1 et que le maximum est la variable $totalPages.
Maintenant si on met 8987 dans l'URL alors que la page maximale est 50, on verra les données de la page 50.

Plus d'infos sur ces fonctions :
Ensuite, nous allons couper notre tableau, pour récupérer uniquement les valeurs de la page qu'on visionne.

PHP:
$offset = ($page - 1) * $limit;
$offset = ($offset < 0) ? 0 : $offset;
$items = array_slice($items, $offset, $limit);

La variable $offset contient un entier qui indique à quel endroit commencer à lire le tableau.
Exemple : Sur la page 10, on affiche les éléments 180 à 200 car la limite par page est 20, il faut donc couper le tableau de 0 à 180, pour garder que les 20 éléments suivants.

Grâce à la fonction array_slice, on coupe notre tableau sans difficulté.


Et voilà, nous avons notre tableau de 200 entrées qui est désormais coupé en 20.
Avant de passer à l'affichage, on va voir comment faire une pagination depuis la base de données.

:induste: Faire une pagination - Depuis la base de données :induste:

Pour cette seconde partie du tutoriel, il vous faudra avoir rempli votre base de données.
On va repartir sur un fichier vierge que je nommerai index_db.php.

On va ensuite lier la base de données.

PHP:
$pdo = new PDO('mysql:host=db_host;dbname=db_name', 'db_user', 'db_pass');

Vous constaterez qu'il y a peu de différences entre la première partie du tutoriel, et la seconde.
On définit la page qu'on visionne, la limite de lignes à afficher par page.

PHP:
$page = (!empty($_GET['page']) && $_GET['page'] > 0) ? intval($_GET['page']) : 1;
$limit = 20;

Ensuite il faut qu'on récupère le total d'entrée dans la base de données, pour déterminer le nombre de pages qu'on aura au total.

PHP:
$totalItems = $pdo->query('SELECT count(id) AS total FROM items')->fetch(PDO::FETCH_ASSOC)['total'];
$totalPages = ceil($totalItems / $limit);

Comme sur la première partie, on "sécurise" notre variable $page, et on récupère l'offset.
PHP:
$page = max($page, 1);
$page = min($page, $totalPages);

$offset = ($page - 1) * $limit;
$offset = ($offset < 0) ? 0 : $offset;

Pour conclure, il faut récupérer tous nos items qui sont dans la base de données, en précisant où commencer et la limite.
PHP:
$items = $pdo->query('SELECT * FROM items ORDER BY id ASC LIMIT '. $offset . ',' . $limit);

C'est tout pour cette seconde partie du tutoriel.

:induste: Affichage des données :induste:

Comme je vous l'ai précisé plus haut, le code que je vous donne ci-dessous fonctionne pour les deux parties, il vous faudra juste faire attention au nom des variables.

HTML:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Paginate</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <table class="table table-hover table-bordered">
        <tr>
            <th>ID</th>
            <th>UserId</th>
            <th>Title</th>
        </tr>
        <?php foreach ($items as $item): ?>
            <tr>
                <td><?= $item['id']; ?></td>
                <td><?= $item['user_id']; ?></td>
                <td><?= $item['title']; ?></td>
            </tr>
        <?php endforeach; ?>
    </table>

    <nav aria-label="Array pagination">
        <ul class="pagination">
            <?php if($page != 1){ ?>
                <li class="page-item">
                    <a class="page-link" href="index.php?page=<?= $page - 1; ?>" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                        <span class="sr-only">Previous</span>
                    </a>
                </li>
            <?php } ?>
            <?php for($i = 1;$i <= $totalPages;$i++) {?>
                <li class="page-item <?= ($i == $page) ? 'active' : ''; ?>"><a class="page-link" href="index.php?page=<?= $i; ?>"><?= $i; ?></a></li>
            <?php } ?>
            <?php if($page < $totalPages){ ?>
                <li class="page-item">
                    <a class="page-link"href="index.php?page=<?= $page + 1; ?>" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                        <span class="sr-only">Next</span>
                    </a>
                </li>
            <?php } ?>
        </ul>
    </nav>
</div>
</body>
</html>

Vous constaterez que j'ai intégré bootstrap, ce n'est qu'une question de design, vous pouvez faire sans ou intégrer un autre framework CSS.

C'est tout pour cette troisième partie concernant l'affichage, je ne m'attarde pas sur ce sujet car j'estime qu'il est relativement simple de manipuler ce code pour l'adapter à vos besoins.

Si vous avez des suggestions d'améliorations, ou des idées d'autres tutoriels à faire, n'hésitez pas à me demander !

:induste: WhiiTe' :induste:
J'ai vu que tu incrémenter de 1 mais comment faire quand je me retrouver avec 100 pages il n'existe pas une technique pour combiner et dire t'es page 50 alors je t'affiche la 1- 48-49-50-51-52-100 car je galère un peu ^^
 

WhiiTe'

Administateur
Ancien staff
Inscription
22 Octobre 2011
Messages
14 704
Réactions
8 499
Points
32 425
J'ai vu que tu incrémenter de 1 mais comment faire quand je me retrouver avec 100 pages il n'existe pas une technique pour combiner et dire t'es page 50 alors je t'affiche la 1- 48-49-50-51-52-100 car je galère un peu ^^
C'est de l'algorithmique, cherche pae toi-même un peu :p
 

Paul GTP

Légende vivante
VIP
Inscription
15 Août 2013
Messages
6 194
Réactions
7 547
Points
24 772
Si vous avez des suggestions d'améliorations, ou des idées d'autres tutoriels à faire, n'hésitez pas à me demander !
I'm here :neo:
--
$totalItems = $pdo->query('SELECT count(id) AS total FROM items')->fetch(PDO::FETCH_ASSOC)['total'];
Il y a plus simple avec PDOStatement::rowCount je trouve :p
Code:
$count = $bdd->query("SELECT * FROM items")->rowCount();
--
$items = $pdo->query('SELECT * FROM items ORDER BY id ASC LIMIT '. $offset . ',' . $limit);
Ici je pense que tu as fait une petite erreur non ? Tu as mis $offset au niveau de LIMIT et $limit après...
Au niveau du nom de tes variables ça ne correspond pas et dans mes scripts de pagination personnellement je préfère rajouter "OFFSET" même si c'est implicite :p
Code:
SELECT [...] LIMIT :limit OFFSET :offset
--
$items = $pdo->query('SELECT * FROM items ORDER BY id ASC LIMIT '. $offset . ',' . $limit);
Par ailleurs, tes requêtes ne sont pas vraiment sécurisées. En un sens oui, vu que tu les sécurises préalablement avec tes min() et max() mais c'est une mauvaise habitude de faire des query quand tu as des variables à manipuler.
Ici, je recommande vivement d'utiliser une requête préparée, ça devrait être le cas à chaque fois que tu manipules une requête avec des variables :p
Code:
$items = $pdo->prepare('SELECT * FROM items ORDER BY id ASC LIMIT :limit OFFSET :offset');
$items->execute([
    'limit' => $limit,
    'offset' => $offset
]);
--
J'ai vu que tu incrémenter de 1 mais comment faire quand je me retrouver avec 100 pages il n'existe pas une technique pour combiner et dire t'es page 50 alors je t'affiche la 1- 48-49-50-51-52-100 car je galère un peu ^^
Dans l'idée, tu peux faire ça (à améliorer :p)
Code:
$page : la page actuelle
$totalPages : le nombre total de pages
x : la dernière page

Si $totalPages > 10
    Afficher les 3 premières pages
    Si !in_array($page != [1, 2, 3, 4, x, x - 1, x - 2, x - 3]
            Afficher "..."
            Afficher $page
            Afficher "..."
        Sinon $page == 4 ou $page == x - 3
            Afficher $page
            Afficher "..."
        Sinon $page == x - 3
            Afficher "..."
            Afficher $page
        Sinon
            Afficher "..."
        Fin Si
    Afficher les 3 dernières pages
Sinon
    Afficher toutes les pages
Fin Si
 
Dernière édition:
Haut