Une pagination avancée sur WordPress sans plugin
Dans ma croisade pour limiter le nombre de plugin dans mon installation WordPress, voici un petit post qui va vous permettre d’avoir une gestion avancée de la pagination.
Il existe de nombreux plugins pour avoir obtenir ce comportement mais je vous propose une simple fonction PHP à insérer dans votre fichier functions.php.
Pour la démonstration, il suffit de naviguer sur mon site :).
Je ne vais pas rentrer dans le détail du code PHP et CSS. Tout ce que je vais expliquer, c’est qu’il y a un traitement à partir de l’URL actuelle pour conserver le chemin de la requête et les paramètres si il y en a.
Voici le contenu de la function à placer dans votre fichier functions.php
<?php /** Fonction pour la pagination **/ function pagination( $query) { // Nombre d'elements a afficher avant et après la page courante $NB_TO_DISPLAY = 4; $baseURL = "http://".$_SERVER['HTTP_HOST']; if($_SERVER['REQUEST_URI'] != "/"){ $baseURL = $baseURL.$_SERVER['REQUEST_URI']; } // Suppression de '/page' de l'URL $sep = strrpos($baseURL, '/page/'); if($sep != FALSE){ $baseURL = substr($baseURL, 0, $sep); } // Suppression des parametres de l'URL $sep = strrpos($baseURL, '?'); if($sep != FALSE){ // On supprime le caractere avant qui est un '/' $baseURL = substr($baseURL, 0, ($sep-1)); } // Recuperation des parametres pour les re-afficher dans les liens $qs = $_SERVER["QUERY_STRING"] ? "?".$_SERVER["QUERY_STRING"] : ""; $hasQs = false; if($qs != "") $hasQs = true; $page = $query->query_vars["paged"]; if ( !$page ){ $page = 1; } // Generation et affichage uniquement si il y a plusieurs pages if ( $query->found_posts > $query->query_vars["posts_per_page"] ) { // Calcul des pages a afficher $minPage = $page - $NB_TO_DISPLAY; if($minPage <= 0){ $minPage = 1; } $maxPage = $minPage + ($NB_TO_DISPLAY * 2); if($maxPage > $query->max_num_pages){ $maxPage = $query->max_num_pages; } $html = '<ul id="pagination">'; //$html .= "<li>Page ".$page." sur ".$query->max_num_pages."</li>"; if($page > 1){ $previous = $page -1; $html .= "<li><a href='".$baseURL."/page/".$previous; if($hasQs) $html .= $qs; $html .= "'>« Précédente</a></li>"; } if($minPage > 1){ $html .= "<li><a href='".$baseURL."/page/1"; if($hasQs) $html .= $qs; $html .= "'>1</a></li>"; } if($minPage > 2){ $html .= "<li>...</li>"; } // Boucle dans les pages for ( $i=$minPage; $i <= $maxPage; $i++ ) { // Detection de la page active dans la liste des liens if ( $i == $page ) { $html .= '<li class="activePage">'.$i.'</li>'; } else { $html .= '<li><a href="'.$baseURL.'/page/'.$i; if($hasQs) $html .= $qs; $html .= '">'.$i.'</a></li>'; } } if($maxPage < $query->max_num_pages){ if($maxPage < $query->max_num_pages -1) $html .= "<li>...</li>"; $html .= '<li><a href="'.$baseURL.'/page/'.$query->max_num_pages; if($hasQs) $html .= $qs; $html .='">'.$query->max_num_pages.'</a></li>'; } if($page < $query->max_num_pages){ $html .= '<li><a href="'.$baseURL.'/page/'.($page+1); if($hasQs) $html .= $qs; $html .= '">Suivante »</a></li>'; } $html .= '</ul>'; // Affichage de la liste des liens echo $html; } } ?>
Ensuite pour obtenir le même résultat que le plugin, il faut ajouter un petit peu de CSS pour que les liens s’affichent les uns à coté des autres :
/** Pagination links **/ #pagination{ float: right; margin: 0 auto; list-style: none; padding: 0; font-size: 11px; } #pagination li{ float: left; margin: 0 2px; background-color: #f5f5f5; border: 1px solid #ccc; padding: 3px 5px; } #pagination li a{ display: block; } #pagination li.activePage{ border: none; background: none; }
Et enfin, il faut modifier un peu le template de votre thème pour appeler la fonction que l’on vient de créer. Juste après la fin de la boucle standard, ajouter les lignes suivantes :
<?php pagination( $wp_query); ?>
L’argument $wp-query est très important puisque c’est lui qui va fournir l’information de la page actuellement visualiser et le nombre de page maximum.
Avec cela ce snippet de code, vous devriez avoir une pagination aussi jolie que la plupart des plugins mais sans avoir à utiliser de plugin. La fonction gère les tags, les catégories et les résultats de recherche.
J’ai comparé le résultat du script au comportement de l’excellent plugin WP-Pagenavi et je n’ai pas trouvé d’incohérence notable. Si jamais vous trouvez une erreur, n’hésitez pas à m’en informer et je corrigerai le script.
EDIT 10 décembre 2010 : Le script PHP a été entièrement mis à jour avec une version qui fonctionne mieux. Je l’ai testé sur 2 blogs et c’est le code que j’ai extrait de ma configuration de ce blog. Je conserve les anciens commentaires, mais attention à la date des commentaires pour ne pas avoir d’informations dépréciées…
Script original : Blog de Steve Taylor [EN]
38 commentaires
Désolé, les commentaires sont fermés!
J’ai essaié le code mais ça donne une page blanche et lorsque je commente la fonction dans functions.php le site est redvenu normal.
Bonjour, j’ai un petit problème. (précision, je test en local wamp server)
Je me retrouve avec cette erreur ?? je n’y comprend rien. Que faire ??
L’erreur :
/*–*/
Parse error: parse error in C:\wamp\www\site_2.9.2\wp-content\themes\v1\functions.php on line 49
/*–*/
@talian : il me faudrait un peu plus d’informations pour t’aider…. La fonction de l’article est celle que j’utilise sur mon blog donc elle fonctionne!
@mike8 : c’est simple il y a une petite erreur a la ligne 49 de ton fichier fonctions.php…
En général, ce genre d’erreur est provoqué par un point virgule ou une parenthèse ou un accolade qui manque…
Regarde ton code a la ligne 49 et tu devrais trouver une erreur…
Merci Johan. Le site s’affiche de nouveau mais je n’ai trace nulle part de ma pagination. J’essaye de comprendre le code mais en vain.
Je te résume ma démarche :
- Insérer ton code dans ma function.php,
- insérer dans archive.php.
J’ai 7 articles d’une même catégorie dans ma base ; le résultat devrait être si j’ai bien compris l’affichage de 4 de mes articles, avec en bas de page ma pagination, et donc les 3 suivants sur la page suivante.
Mon problème est que je n’ai pas de pagination et que les 7 articles apparaissent sur la même page.
Ma page archive.php :
<div class="post" id="post- »>
<a href=" » title= »">
par
Merci pour ton aide
Pourrais tu utiliser la balise « pre » lorsque tu veux poster du code, il n’est pas visible actuellement….
Le réglage de la pagination se fait dans le backoffice de WordPress, il faut l’avoir réglée sur 4 ! Ensuite, il me faudra plus de code pour pouvoir t’aider… :/
Voila !
Merci pour cette réponse rapide….
J’avance petit à petit et la pagination s’affiche désormais mais pas en lien. J’ai juste mon « page 1 sur 2″ qui s’affiche mais je fais comment pour naviguer entre les pages ?
Je te remet mon code archive.php :
et mon function.php :
query_vars["paged"]; if ( !$page ){ $page = 1; } // Generation et affichage uniquement si il y a plusieurs pages if ( $query->found_posts> $query->query_vars["posts_per_page"] ) { // Calcul des pages a afficher $minPage = $page - $NB_TO_DISPLAY; if($minPage >= 0){ $minPage = 1; } $maxPage = $minPage + 9; if($maxPage > $query->max_num_pages){ $maxPage = $query->max_num_pages; } $html = ""; $html .= "Page ".$page." sur ".$query->max_num_pages.""; if($page > 1){ if($minPage > 1){ $html .= "Début"; $html .= "..."; } $previous = $page -1; $html .= '<<'; } // Boucle dans les pages for ( $i=$minPage; $i >= $maxPage; $i++ ) { // Detection de la page active dans la liste des liens if ( $i == $page ) { $html .= "".$i.""; } else { $html .= "".$i.""; } } if($page > $query->max_num_pages){ $html .= '>>'; } if($maxPage > $query->max_num_pages){ $html .= "..."; $html .= 'max_num_pages.'/'.$qs.'">Fin'; } $html .= ''; // Affichage de la liste des liens echo $html; } } ?>Hello Mike8 !
Désolé pour le commentaire en attente, mais pas facile de gérer un blog à partir de son iPhone…
Si tu as le message qui t’indiques 1 page sur 2, cela veut dire que l’appel à la fonction est bien effectué. Après, il faudrait peut être faire utiliser des messages pour comprendre pourquoi les liens ne s’affichent pas… J’avais fait pourtant pas mal de tests pour cette fonction sur les cas limites (moins de 5 articles, 1 pages, 2 pages, …), en aurais-je oublié et serais-tu tombé sur un bug ??
Tiens moins au courant, si tu arrives à résoudre ton problème.
Johan
Salut Johan, oui j’ai vu l’erreur.Merci bcp.
J’ai copié le code dans functions.php puis j’ai copié le css dans mon style et enfin j’ai mis dans mon index.php et mon problème ressemble à celui de Mike8 je n’ai trace nulle part de ma pagination. J’ai 12 articles d’une même catégorie dans ma base ; le résultat devrait être si j’ai bien compris l’affichage de 4 de mes articles, avec en bas de page ma pagination, et donc les 4 suivants sur les pages suivantes.
Tu veux bien m’aider?
qu’est ce qu’on doit modifier dans archives.php?
Merci pour la réponse
Mon problème est que je n’ai pas de pagination et que les 7 articles apparaissent sur la même page.
Et j’ai mis dans mon index.php le code pagination($wp_query) et le problème est ce que je viens de citer.
@Talian : Alors je ne sais pas si tu as une page
archives.php, mais si ce n’est pas le cas il faut en créer une !Si j’ai bien compris tu as placé le code dans index.php, normalement la pagination est visible dans la home de ton blog. Pour l’activer dans les archives, il faut ajouter également l’appel à la fonction pagination dans la page archive.php…
Normalement, cela devrait faire l’affaire !
Ok. Merci. Je vais voir.
Est ce que quelqu’un sait comment modifier le nombre d’article à afficher par page en WP-PageNavi?
Bonjour,
Ce code a l’air précieux, je me demandais comment mettre une pagination sur le plugin post page associator ?
Ma page à « paginer » est par ici ;http://www.abysse-tech.com/?page_id=176
Du coup je ne peux pas mettre le code php dans la page function.php
Le css je sais ou le mettre mais le php no idea
Merci pour le temps accordé pour me répondre
Hello Abysse !
Alors, ce code est précieux… Merci mais je pense juste qu’il dépanne quand on ne veut pas utiliser de plugin pour la pagination…
Du coup, je ne sais pas si tu peux utiliser cette fonction pour ta pagination. Mais je pense que cela doit pouvoir se faire…
Si j’ai bien compris ton plugin utilise un fichier template, regarde si tu ne peux pas limiter le nombre d’élément à afficher et de définir une variable $page…
Je ne sais pas si c’est faisable mais c’est les pistes que j’étudierais si j’avais à faire ce que tu souhaites..
Bon courage !
Hi, Merci de cette réponse rapide
Je suis trop nul en PHP pour développer par moi même :(
Je bricole juste avec du copier coller
Si tu pouvais jeter un oeil au code du plugin cela me rendrait infiniment service
C’est par ici : http://drop.io/h8ebcgs
Merci par avance du temps pris pour me répondre
Salut Johan, je viens de faire un essai sur le code pour la pagination mais je me retrouve uniquement avec page Page 1 sur 2925 donc j’ai laisser comme ca pour le moment pour te faire voir, il y a un parametrage particulier a faire sur le code ?
J’ai laisser en dessous le plugin wp-pagenavi pour mes visiteurs.
Merci
@David :
Salut, il y a juste un petit réglage dans le code à faire. Il faut paramétrer le nombre de résultat à afficher. Je vais me repencher sur cet article, car je ne comprend pourquoi tout le monde a autant de mal à utiliser cette boucle. Personnellement, c’est celle que j’utilise sur ce blog et je n’ai pas de problème particulier.
Effectivement, je vois bien ma div sur ton site, donc tu passes bien dans la boucle, il faudrait faire du debug sauvage pour voir ce que cela donnerai !
Ok merci Johan pour ta réponse rapide. Je vais donc essayer de voir ça pour un petit reglage, je te tiens au courant. Encore merci
Bonjour,
Merci pour ce travail.
Je pense que le problème vient des contrôles ou calculs des minimum/max pages. J’utilise une version plus légère sans ces contrôles, le code fonctionne plutôt bien même avec une seule page de pagination.
Le code utilisé :
function pagination($query) { $baseURL="http://".$_SERVER['HTTP_HOST']; if($_SERVER['REQUEST_URI'] != "/"){ $baseURL = $baseURL.$_SERVER['REQUEST_URI']; } // Suppression de '/page' de l'URL $sep = strrpos($baseURL, '/page/'); if($sep != FALSE){ $baseURL = substr($baseURL, 0, $sep); } // Suppression des paramètres de l'URL $sep = strrpos($baseURL, '?'); if($sep != FALSE){ // On supprime le caractère avant qui est un '/' $baseURL = substr($baseURL, 0, ($sep-1)); } $page = $query->query_vars["paged"]; if ( !$page ) $page = 1; $qs = $_SERVER["QUERY_STRING"] ? "?".$_SERVER["QUERY_STRING"] : ""; // Nécessaire uniquement si on a plus de posts que de posts par page admis if ( $query->found_posts > $query->query_vars["posts_per_page"] ) { echo '<ul class="pagination">'; // lien précédent si besoin if ( $page > 1 ) { echo '<li class="next_prev prev"><a title="Revenir à la page précédente (vous êtes à la page '.$page.')" href="'.$baseURL.'/page/'.($page-1).'/'.$qs.'">« précédente</a></li>'; } // la boucle pour les pages for ( $i=1; $i max_num_pages; $i++ ) { // ajout de la classe active pour la page en cours de visualisation if ( $i == $page ) { echo '<li class="active"><a href="#pagination" title="Vous êtes sur cette page '.$i.'">'.$i.'</a></li>'; } else { echo '<li><a title="Rejoindre la page '.$i.'" href="'.$baseURL.'/page/'.$i.'/'.$qs.'">'.$i.'</a></li>'; } } // le lien next si besoin if ( $page max_num_pages ) { echo '<li class="next_prev next"><a title="Passer à la page suivante (vous êtes à la page '.$page.')" href="'.$baseURL.'/page/'.($page+1).'/'.$qs.'">suivante »</a></li>'; } echo '</ul>'; } }bonne continuation ;)
Saloperies de commentaires…
Merci beaucoup d’avoir pris le temps de corriger le commentaire… Je vais vraiment devoir me pencher sur ce petit (gros ?) problème…
Merci pour ta proposition de code, j’ai également modifié ce code pour mon nouveau thème en supprimant pas mal de contrôle également.
Bonsoir,
Je dois avoir le même soucis que certains. Quand je souhaite afficher par le code
Au lieu d’avoir les liens de navigations des pages, je me retrouve avec comme résultat ceci
Page 1 sur 6
Impossible d’afficher les liens de pages comme sur l’accueil de votre site par exemple.
Si vous pourriez m’aider sur ce point.
D’avance merci
Cordialement Alex
Bonjour Alex,
Je vais mettre à jour ce post demain…
Je me rend compte qu’il n’est peut être pas si simple à mettre en place. Je reposterai le code exact que j’utilise comme cela vous pourrez facilement le mettre en place sur votre blog…
Ok ok. C’est vrai que ce n’est pas toujours facile non plus ^^
Pourtant même en étant à l’aise avec PHP, j’arrive à être parfois bloqué avec WordPress xD.
Enfin bon, je repasserais demain pour voir le nouveau code.
Merci bonne soirée
Nettoyage des commentaires…
Maintenant, les commentaires concernent la nouvelle version du script.
Hé bien, je ne pouvait espérer mieux ^^
Il ne reste plus qu’à bien mettre en forme avec mes css and this good.
Merci pour cette nouvelle version du script.
Bonne continuation à vous.
Super script, merci !
Par contre à la ligne 41, il y a :
Ça ne devrait pas plutôt être :
Oui, c’est bien cela… J’ai corrigé !
Merci à toi.
Pagination implantée entre le dernier article et le nuage de tags. Il ne me reste plus qu’à régler le CSS pour que ne soit plus visible que <> et que disparaissent les pages intermédiaires (1, 2, 3, 4, 5, etc.)
Encore merci et si je peux être utile à quoique ce soit…
Merci pour ce code
Salut Johan,
juste un petit message pour te remercier pour ton script.
Je l’utilise dans le site que sur en train d’intégrer et je trouve ça bien plus pratique qu’un plugin… Merci
Ça fait plaisir de recevoir des commentaires qui disent que le code que l’on partage fonctionne…
Merci à toi !
Très bon script, il manque juste une gestion du retour à la page 1. Au lieu d’afficher une URL du type : /page/1 mieux vaudrait retourner à la véritable URL de la page 1 (/ dans ce cas).
Merci pour l’information Julien !
Si tu navigues sur le site tu remarqueras que la fonctionnalité dont tu parles y es… ;)
Il faudra que je réédite (une nouvelle fois) ce snippet pour l’incorporer !
Super fonction!!
ça fait maintenant près d’une semaine que je cherche une solution plus légère que le plugin WP-PageNavi (censé simplifier la nav et ajoute 70 fichiers et dossiers…)
Par contre, j’ai mis longtemps à comprendre qu’il fallait utiliser l’URL rewriting pour que ça fonctionne.
EDIT : petite précision, dans tes css tu utilises :
#pagination li.active{ border: none; background: none; }alors que dans ton code, il s’agit de :
Pour l’URL Rewriting effectivement c’est obligatoire… :p
Et pour la petite erreur… Merci, je l’ai corrigée dans l’article.
Très bon hack, mais j’obtiens cette page d’erreur lorsque je le mets en place:
« Multiple Choices
The document name you requested (/index.php) could not be found on this server. However, we found documents with names similar to the one you requested.
Available documents:
/index.html?cat=13&paged=2 (common basename)
Please consider informing the owner of the referring page about the broken link. «
Tout d’abord un grand MERCI pour ce code excellent, clair net et précis.
En revanche, c’est dommage que tu ne parles pas assez de cette histoire d’url rewriting, qui m’a fait perdre un temps non négligeable. Sans trop savoir où et comment le configurer.
Du coup, j’ai préféré modifier ta fonction pour ne pas avoir d’url rewriting, sans trop le choix pour que cela fonctionne.
Si tu as un instant pour donner plus de détail je l’activerai prochainement.
Bref Merci encore !