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">« Inizio</a></li>'; else echo '<li class="first-page">« 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 »</a></li>'; else echo '<li class="last-page">Fine »</li>'; } public function getPrev() { if($this->_currentPage - 1 > 0) echo '<li class="prev-page"><a href="' . $this->_redirectTo . 'p='. ($this->_currentPage - 1) .'" title="Precedente">< Precedente</a></li>'; else echo '<li class="prev-page">< 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 ></a></li>'; else echo '<li class="next-page">Successiva ></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
Download12 commenti
Trackback e pingback
Non ci sono trackback e pingback disponibili per questo articolo
Grazie Nicola, potresti fare uno zip con le istruzioni allegate da scaricare e trasformare l’articolo in un’ottima risorsa scaricabile per tutti, che ne dici? ;)
Certamente! É giá in preparazione. Abbiamo avuto dei problemi con questa pubblicazione, per questo non é ancora disponibile. Lo metteremo online nel primo pomeriggio!
Chiedo scusa a tutti gli utenti.
L’ultimo ciclo for della funzione getPager può essere sostituito da un foreach.
Poi non si potrebbe aggiungere una funzione che pagina i risultati di una query?
Io la mia classe l’ho già fatta, ma mi mancavano i numeri delle pagine.
Grazie.
Grazie a te Pietro.
Volendo potresti usare un foreach ma non cambierebbe gran che.
La query avevo anche pensato di inserirla, ma per come l’avevo pensato io, dovevo inserire anche il database e non mi andava molto a genio. Quindi ho evitato.
Ho scovato un piccolo bug nella classe. Ho aggiornato sia l’articolo e in giornata sará disponibile anche il file aggiornato per il download.
Riguardo il bug, ho aggiunto nel costruttore un quarto parametro che specifica a quale pagina far puntare i link della paginazione.
Scusatemi ancora per i disagi.
Non hai messo il punto interrogativo negli url :D
Lo so, é voluto. Perché nel caso io abbia giá altre GET, mi darebbe errore. Quindi il modo giusto di passarlo ad esempio sarebbe ‘index.php?’.
Infatti, se noti nel costruttore, il parametro di default é proprio ‘index.php?’
Ciao Nicola, complimenti per la classe: pulita e ben fatta.
Io autodidatta mi è servita molto per capire come non complicarmi troppo la vita :)
Se posso permettermi (ma è solo una finezza): una volta cliccata la penultima pagina, ne viene visualizzata una di troppo in coda.
L’ho risolto così:
/** BugFix
* inserito alla linea 152 */
if(end($return) > $total){
array_pop($return);
array_unshift($return,reset($return)-1);
}
/** end BugFix */
Grazie Luca, e grazie anche per il bugfix!
Ciao, innanzitutto complimenti per l’articolo.
premetto che non sono per niente esperto di php, cmq io sto cercando di costruire un sito in php, ma poi al suo interno vorrei inserire un blog.
Con wordpress me la cavo ma non si può inserire un cms all’interno di un sito…
si può usare una sorta di backdesk come quello di wordpress solo per quella parte di sito?
o si può inserire in un sito un blog tipo wordpress che mi permetta di aggiungere articoli tag… facilmente?
grazie!
Ciao Luca e grazie!
Volendo puoi installare WP in una sottocartella del tuo sito e usarlo come blog!
ciao, complimenti per l’articolo, ma sono agli inizi con php. Sono riuscito a fatica a implementare la classe a alla fine la pagina finalmente mi restituisce senza errori questo risultato senza link però per spezzare una serie di 15 riquadri-id-post che ho a video in più parti, l’impostazione del numero di pagine desiderato funziona ma dove manco poi il lavoro sporco? Grazie per eventuali suggerimenti
1
2
« Inizio
Fine »