Aller au contenu

[Snippet #03 - PHP] pagination

Lorsqu'on réalise un site web, on a toujours, à un moment ou à un autre, besoin de réaliser une pagination avec des liens vers les autres pages.

Comme ce genre de code se ressemble toujours, et qu'on a vite tendance à y oublier un +1/-1, j'ai décidé de me faire une petite fonction dédiée et de vous la partager.

<?php
/**
 * Generate an array of pagination link where the key is a page number
 * and the value is a type of link (current page, normal link, first/last page link)
 * @param  integer $currentPage   the current displayed page
 * @param  integer $totalPages    the total number of pages (can be replaced by the two following params)
 * @param  integer $itemPerPage   the number of item displayed on each page
 * @param  integer $totalItems    the total number of existing items
 * @param  integer $nbPagesAround the maximum number of links (excluding first/last) that should be displayed before or after the current page
 * @return array                  the pagination array (key = page to link to, value = type of link)
 */
function generatePagination(
    $currentPage,
    $totalPages = 0,
    $itemPerPage = 0,
    $totalItems = 0,
    $nbPagesAround = 2
) {
    $pagination = array();

    if($totalPages == 0) {
        if($itemPerPage == 0 || $totalItems == 0) {
            return false;
        } else {
            $totalPages = (int)ceil($totalItems / $itemPerPage);
        }
    }

    if($currentPage > $nbPagesAround + 2) {
        $pagination[1] = self::PAGINATION_FIRST;
    } elseif($currentPage > $nbPagesAround + 1) {
        $pagination[1] = self::PAGINATION_LINK;
    }
    for($i = ($currentPage - $nbPagesAround); $i < $currentPage; $i++) {
        if($i > 1 || ($i == 1 && $currentPage <= $nbPagesAround + 1)) {
            $pagination[$i] = self::PAGINATION_LINK;
        }
    }
    $pagination[$currentPage] = self::PAGINATION_CURRENT;
    for($i = ($currentPage + 1); $i < ($currentPage + $nbPagesAround + 1); $i++) {
        if($i < $totalPages
            || ($i == $totalPages && $currentPage >= $totalPages - $nbPagesAround)
        ) {
            $pagination[$i] = self::PAGINATION_LINK;
        }
    }
    if($currentPage < ($totalPages - $nbPagesAround - 1)) {
        $pagination[$totalPages] = self::PAGINATION_LAST;
    } elseif($currentPage < ($totalPages - $nbPagesAround)) {
        $pagination[$totalPages] = self::PAGINATION_LINK;
    }

    // ksort($pagination);

    return $pagination;
}

Ce code vous retournera un tableau avec la liste des pages vers lesquels vous devrez faire des liens. Pour chaque élément du tableau

  • La clé : numéro de la page
  • La valeur : type de lien, suivant le modèle suivant :
    • link : lien classique vers une autre page
    • current : item pour la page courante (généralement affiché dans un thème différent, et sans lien
    • first : lien vers la toute première page (généralement affiché avec «).
    • last : lien vers la toute dernière page (généralement affiché avec »).

Il n'y a ensuite plus qu'à gérer l'affichage dans votre vue (ici, exemple réalisé avec le gestionnaire de template rainTPL) :

<div class="pagination">{loop="pagination"}
    {if="$value == 'current'"}
        <span>{$key}</span>
    {else}
        {if="$value == 'last'"}&hellip;{/if}
        <a href="path/to/my/list/{$key}">
            {if="$value == 'first'"}
                &laquo;
            {elseif="$value == 'last'"}
                &raquo;
            {else}
                {$key}
            {/if}
        </a>
    {/if}
    {if="$value == 'first'"}&hellip;{/if}
    {/loop}
</div>

Avec un peu de CSS, on arrive à un résultat sympa :

Aperçu pagination

En espérant que ça puisse être utile à quelqu'un.

Keep cool & rock on.