PHP: Come creare una paginazione funzionale?

La paginazione é parte fondamentale di ogni sito che necessiti di gestire e mostrare nel modo più intuitivo e ordinato possibile una mole massiccia di contenuti. Per esempio, immagina YIW senza la paginazione a piè di pagina: dopo tre anni di blogging ci troveremmo in home page centinaia di articoli da consultare, con un effetto decisamente poco usabile. Con questo tutorial vedremo come creare, passo dopo passo, una paginazione molto semplice e funzionale in PHP. Rimbocchiamoci le maniche ed iniziamo!

Tipi di paginazione

Esistono vari tipi di paginazione. La differenza tra esse é minima, in quanto generalmente cambia soltanto il modo con il quale viene creata la lista di pagine. Su molti siti viene usata una paginazione che stampa tutte le pagine presenti una di seguito all’altra, un espediente utile solo finché si hanno poche pagine, poichè quando iniziano a diventare molte, la lista diventa troppo lunga e disordinata. In caso di contenuti abbastanza corposi, è preferibile usare una “paginazione ad estratti”. Per paginazione ad estratti ci riferiamo a quella paginazione che non mostra tutte le pagine presenti, ma solo un determinato numero in base alla pagina in cui ci si trova. Un classico esempio di questo tipo di paginazione lo troviamo su Google:prova a fare una ricerca con una query qualunque. Dopodiché clicca sulla pagina numero 10 e guarda cosa accade alla paginazione. Le pagine mostrate sono sempre 10, dalla 5 alla 14, navigabili con i tasti “Avanti” e “Indietro”. Questa é la paginazione che creeremo noi.

In codice

Il codice é leggermente complesso poiché ci sono un po’ di calcoli da fare per capire quante pagine stampare prima e dopo quella attuale. Iniziamo quindi a creare la classe YCPager:

class YCPager {

    private $_currentPage = 0;
    private $_totalRows = 0;
    private $_prevLink = 2;
    private $_nextLink = 2;
    private $_queryLimit = 0;
    private $_numPerPage = 0;
    private $_redirectTo = '';

    public function __construct($currentPage, $totalRows, $numPerPage, $redirectTo = 'index.php?') {
        $this->_currentPage = (int) max($currentPage, 1);
        $this->_totalRows = (int) max ($totalRows, 1);

        $this->_numPerPage = (int) $numPerPage;
        $this->_redirectTo = $redirectTo;
    }

Fin qui é tutto semplice. Sono state create le proprietá della classe ed inizializzate tramite il costruttore. Le proprietá $_prevLink e $_nextLinkindicano quante pagine vuoi che vengano mostrate prima e dopo la pagina attuale. Se non vengono modificate, vengono mostrate un totale di 5 pagine. Il costruttore inizializza le proprietá impostando la pagina attuale in cui ci si trova. Il numero totale di righe per le quali creare una paginazione e il numero di righe che si vogliono mostrare in ogni pagina. Successivamente aggiungi due metodi per ottenere dei dati che utilizzerai nelle tue pagine per eseguire correttamente le query sul database.

    public function getOffset() {
        return ceil($this->_totalRows/$this->_numPerPage);
    }

    public function getQueryOffset() {
        return ($this->_currentPage == 1) ? $this->_queryLimit : ($this->_currentPage - 1) * $this->_numPerPage;
    }

Il metodo getOffset() restituisce il numero totale di pagine che verranno create in base al numero totale di righe inizializzato precedentemente e al numero di righe che vuoi mostrare in ogni pagina. Il metodo getQueryOffset()invece, restituisce il numero da assegnare ad OFFSET nella query del database. Ed ora il metodo per creare la paginazione:

public function getPager() {
        $currentPage = $this->_currentPage;
        $prev = $this->_prevLink;
        $next = $this->_nextLink;
        $total = $this->getOffset();

        echo '<div class="pagination">';
        echo '<ul>';

        $this->getFirst();
        $this->getPrev();

        if($total < ($prev + $next + 1)) {
            $prev = 0;
            $next = 0;
            for($i = $total; $i > 0; $i--) {
                $return[$i] = $i;
            }
        } else {
            if($currentPage == $total) {
                if($currentPage - ($prev + $next + 1) >= 0) {
                    for($i = $total; $i > ($total - ($prev + $next + 1)); $i--) {
                        $return[$i] = $i;
                    }
                }
            } else if($currentPage < $total) {
                if($currentPage - $prev > 0) {
                    for($i = $currentPage - $prev; $i <    $currentPage + $next + 1; $i++) {
                        $return[$i] = $i;
                    }
                } else if($currentPage - $prev <= 0) {
                    for($i = 1; $i <= ($prev + $next + 1); $i++) {
                        $return[$i] = $i;
                    }
                }
            }
        }

        if(!empty($return)) { sort($return); }

        for($i = 0; $i < count($return); $i++) {
            if($return[$i] != $this->_currentPage)
                echo '<li class="number-page"><a href="' . $this->_redirectTo . 'p='. $return[$i] .'" title="">'. $return[$i] .'</a></li>';
            else
                echo '<li class="actual-page"><span>'. $return[$i] .'</span></li>';
        }

        $this->getNext();
        $this->getLast();

        echo '</ul>';
        echo '</div>';
        echo '<div class="clearer"></div>';
    }

Questo metodo non fa altro che eseguire dei calcoli e stampare il numero corretto di pagine successive e precedenti a quella attuale, preoccupandosi di tenere quest’ultima sempre al centro della paginazione. Ora, aggiungi altri quattro metodi. Vengono utilizzati nel metodo getPager()per stampare i link testuali per la prima e l’ultima pagina e la precedente e la successiva a quella attuale:

    public function getFirst() {
        if($this->_currentPage != 1)
            echo '<li class="first-page"><a href="' . $this->_redirectTo . 'p=1" title="Inizio">&#171; Inizio</a></li>';
        else
            echo '<li class="first-page">&#171; Inizio</li>' ;
    }

    public function getLast() {
        if($this->_currentPage != $this->getOffset())
            echo '<li class="last-page"><a href="' . $this->_redirectTo . 'p='. $this->getOffset() .'" title="Fine">Fine &#187;</a></li>';
        else
            echo '<li class="last-page">Fine &#187;</li>';
    }
	
    public function getPrev() {
        if($this->_currentPage - 1 > 0)
            echo '<li class="prev-page"><a href="' . $this->_redirectTo . 'p='. ($this->_currentPage - 1) .'" title="Precedente">&lt; Precedente</a></li>';
        else
            echo '<li class="prev-page">&lt; Precedente</li>';
    }
    
    public function getNext() {
        if($this->_currentPage + 1 <= $this->getOffset())
            echo '<li class="next-page"><a href="' . $this->_redirectTo . 'p='. ($this->_currentPage + 1) .'" title="Successiva">Successiva &gt;</a></li>';
        else
            echo '<li class="next-page">Successiva &gt;</li>';
    }

Ora siamo in grado di stampare i link testuali per la prima e l’ultima pagina e la precedente e la successiva a quella attuale. Nel caso ci si trovi già nella prima o nell’ultima pagina, questi link non saranno cliccabili ovviamente. Con questi metodi possiamo dire di aver concluso la classe YCPager e la paginazione ad estratti. Se hai suggerimenti per aiutarmi a migliorare il metodo descritto nell’articolo lascia un commento!

Scarica i file del tutorial

Download
Tag: ,

L'autore

Sviluppo per il web da alcuni anni. Ultimamente mi sono specializzato in WordPress tramite Your Inspiration, con il quale attualmente lavoro nell'area di supporto clienti e sviluppo temi e plugin per WP.

Sito web dell'autore | Altri articoli scritti da

Articoli correlati

12 commenti

Trackback e pingback

Non ci sono trackback e pingback disponibili per questo articolo