Bonjour,

Je voudrais faire une pagination intelligente, c'est à dire exactement comme le site de Grafikart
Comme ceci :

Mon code actuel affiche la pagination classique (toute les pages)

Mon contrôleur :

$res = $this->Post->query("SELECT COUNT(id) AS nbPosts FROM posts");
        $nbPosts = intval($res[0]->nbPosts);
        $perPage = 1;
        $nbPages = ceil($nbPosts / $perPage);

        if (isset($_GET["p"]) && intval($_GET["p"]) !== 0 && intval($_GET["p"]) <= $nbPages) {
            $p = $_GET["p"];
        } else {
            if ($_SERVER["REQUEST_URI"] !== $this->getRoute("admin.post.index")) {
                header("Location: " . $this->getRoute("admin.post.index"));
            }
            $p = 1;
        }

        $posts = $this->Post->query("SELECT * FROM posts ORDER BY date DESC LIMIT ".($p-1)*$perPage.",$perPage");

Ma vue :

<?php if ($nbPosts > $perPage) : ?>
    <div class="pagination" id="pagination">
        <?php for ($i=1; $i < $nbPages+1; $i++) : ?>
            <?php if ($i === 1) : ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>"><?= $i; ?></a>
            <?php else : ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $i; ?>"><?= $i; ?></a>
            <?php endif; ?>
        <?php endfor; ?>
    </div>
<?php endif; ?>

Le résultat :

11 réponses


shadowkamikaze
Auteur
Réponse acceptée
AlexJM

Ton script fonctionne correctement, je l'ai adapté à mon application, cepandant il y a beaucoup de conditions ^^
Ton script manquait quelques vérifications rien de méchant.
S'il y a des choses à changer pour l'optimisation de mon code, dites le moi merci.

Voici mon code :

Contrôleur

public function index() {
        // Variables pour la pagination
        $res = $this->Post->query("SELECT COUNT(*) AS nbPosts FROM posts", "", true);
        $nbPosts = intval($res->nbPosts);
        $itemsPerPage = 1;
        $nbPages = intval(ceil($nbPosts / $itemsPerPage));
        $nbLinks = 9;

        // Récupération du numéro de la page courante
        if (isset($_GET["p"]) && intval($_GET["p"]) > 0 && intval($_GET["p"]) <= $nbPages) {
            $currentPage = $_GET["p"];
        } else {
            if ($_SERVER["REQUEST_URI"] !== $this->getRoute("admin.post.index")) {
                header("Location: ".$this->getRoute("admin.post.index"));
            }
            $currentPage = 1;
        }

        // Traitement de la pagination
        $halfTotalLinks = floor($nbLinks / 2);
        $start = $currentPage - $halfTotalLinks;
        $end = $currentPage + $halfTotalLinks;

        // Variables renvoyées à la vue
        $name = "posts";
        $posts = $this->Post->query("SELECT * FROM posts ORDER BY date DESC LIMIT ".($currentPage - 1) * $itemsPerPage.",".$itemsPerPage);
        $category = $this->Category;
        $pagination = [
            "nbPosts"           => $nbPosts,
            "itemsPerPage"      => $itemsPerPage,
            "lastPage"          => $nbPages,
            "currentPage"       => $currentPage,
            "nbLinks"           => $nbLinks,
            "start"             => $start,
            "end"               => $end,
            "halfTotalLinks"    => $halfTotalLinks
        ];

        $this->setTitle("Articles");
        $this->render("admin/posts/index", compact("name", "posts", "category", "pagination"), "admin");
    }

Vue

<?php if ($pagination["nbPosts"] > $pagination["itemsPerPage"]) : ?>
    <ul class="pagination">
        <li>
            <?php if ($pagination["currentPage"] === 1) : ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>" class="active">1</a>
            <?php else: ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>">1</a>
            <?php endif; ?>
        </li>
        <?php if ($pagination["currentPage"] > $pagination["halfTotalLinks"] + 1) : ?>
            <li><span class="more">...</span></li>
        <?php endif; ?>

        <?php for ($i = 1; $i <= $pagination["lastPage"]; $i++) : ?>
            <?php if ($pagination["start"] < $i && $i < $pagination["end"]) : ?>
                <?php if ($i !== 1 && $i !== $pagination["lastPage"]) : ?>
                    <li>
                    <?php if ($pagination["currentPage"] === $i) : ?>
                        <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $i; ?>" class="active"><?=$i?></a>
                    <?php else: ?>
                        <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $i; ?>"><?=$i?></a>
                    <?php endif; ?>
                    </li>
                <?php endif; ?>
            <?php endif; ?>
        <?php endfor; ?>

        <?php if ($pagination["currentPage"] < $pagination["lastPage"] - ($pagination["halfTotalLinks"] + 1)) : ?>
            <li><span class="more">...</span></li>
        <?php endif; ?>
        <li>
            <?php if ($pagination["currentPage"] === $pagination["lastPage"]) : ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $pagination["lastPage"]; ?>" class="active"><?= $pagination["lastPage"]; ?></a>
            <?php else: ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $pagination["lastPage"]; ?>"><?= $pagination["lastPage"]; ?></a>
            <?php endif; ?>
        </li>
    </ul>
<?php endif; ?>

Il te faut filtrer ça dans la boucle qui génère ta pagination, en n'affichant que les 3 premières et la dernière (par exemple).

<?php if ($nbPosts > $perPage) : ?>
    <div class="pagination" id="pagination">
        <?php for ($i=1; $i < 4; $i++) : ?>
            <?php if ($i === 1) : ?>
                <a href="<?= $this->getRoute("admin.post.index"); ?>"><?= $i; ?></a>
            <?php else : ?>
                 <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $i; ?>"><?= $i; ?></a>
            <?php endif; ?>
        <?php endfor; ?>
         <div class="separator">...</div>
         <a href="<?= $this->getRoute("admin.post.index"); ?>?p=<?= $nbPosts ; ?>"><?= $nbPosts ; ?></a>
    </div>
<?php endif; ?>

C'est la version "sale", je te laisse refactorer ;)

http://stackoverflow.com/questions/28240777/custom-pagination-view-in-laravel-5 regarde la deuxième partie de la première réponse. Certes c'est du blade, mais le blade n'est pas trop compliqué

Edit : finalement, essaye ça :

<?php
// config
$link_limit = 7; // maximum number of links (a little bit inaccurate, but will be ok for now)
$last_page = X;// ton calcul doit trouver la dernière page
$current_page = X;// ton calcul doit trouver la page courrante
if ($last_page > 1):
    ?>
    <ul class="pagination">
        <!-- DÉBUT : lien pour la première page -->
        <li class="<?= ($current_page == 1) ? ' disabled' : '' ?>">
            <a href="/ton/lien/pour/la/premiere/page">First</a>
        </li>
        <!-- FIN : lien pour la dernière page-->

        <!-- DÉBUT : pagination 'intelligente' -->
        <?php
        for ($i = 1; $i <= $last_page; $i++):
            $half_total_links = floor($link_limit / 2);
            $from = $current_page - $half_total_links;
            $to = $current_page + $half_total_links;
            if ($current_page < $half_total_links) {
               $to += $half_total_links - $current_page;
            }
            if ($last_page - $current_page < $half_total_links) {
                $from -= $half_total_links - ($last_page - $current_page) - 1;
            }
            if ($from < $i && $i < $to):
                ?>
                <li class="<?= ($current_page == $i) ? ' active' : '' ?>">
                    <a href="/ton/lien/pour/la/$i eme/page"><?=$i?></a>
                </li>
                <?php
            endif;
        endfor;
        ?>
        <!-- FIN : pagination 'intelligente' -->

        <!-- DÉBUT : lien pour la dernière page -->
        <li class="<?= ($current_page == $last_page) ? ' disabled' : '' ?>">
            <a href="/ton/lien/pour/la/dernière/page">Last</a>
        </li>
        <!-- FIN : lien pour la dernière page -->
    </ul>
<?php
endif;
?>

Je t'ai déjà adapté le code depuis du blade, à toi de le faire pour qu'il corresponde à ton code ;)

Pour compter le nombre de résultats, c'est quoi la solution la plus rapide ?

Une requête SQL :

$res = $this->Post->query("SELECT COUNT(*) AS nbPosts FROM posts", "", true);
$nbPosts = intval($res->nbPosts);

Ou la fonction count de PHP

$nbPosts = count($this->Post->query("SELECT * FROM posts"));

Autre cas :

// Je fait ma requête SQL pour afficher mes articles
$posts = $this->Post->query("SELECT * FROM posts ORDER BY date DESC";

// Pour compter les résultats une 2ème requête SQL ou la fonction count
count($posts);

l'autre cas car tu ne fais qu'une requête ;)

Et pour les 2 première solutions ?

je dirais le count en SQL, surtout avec un grand nombre de données, avec un petit nombre c'est moins significatif je pense

Ok merci de ta réponse ^^

Sinon pour mes fichiers (la pagination) il y a moyen de les optimiser plus ?

Mis à part de remplacer ça :

if (isset($_GET["p"]) && intval($_GET["p"]) !== 0 && intval($_GET["p"]) <= $nbPages) {
$p = $_GET["p"];
} else {
if ($_SERVER["REQUEST_URI"] !== $this->getRoute("admin.post.index")) {
header("Location: ".$this->getRoute("admin.post.index"));
}
$p = 1;
}

$currentPage = intval($p);

par ça :

if (isset($_GET["p"]) && intval($_GET["p"]) > 0 && intval($_GET["p"]) <= $nbPages) {
$currentPage = intval($_GET["p"]);
} else {
if ($_SERVER["REQUEST_URI"] !== $this->getRoute("admin.post.index")) {
header("Location: ".$this->getRoute("admin.post.index"));
}
$currentPage = 1;
}

Je pense pas

Oui j'ai zaaper cette variable ^^, j'ai fait la modification
Merci pour vos réponses et votre réactivité