Here With Me

Le blog technique d'Amaury Balmer qui parle de technologies open-source, mais surtout de WordPress !

Fixer un nombre d’articles différents selon la vue ou l’on se situe dans WordPress

| 57 Commentaires

Lorsqu'on travaille sur des assez complexes, disons orienté magazine, on a généralement besoin d'afficher un nombre d'articles différents selon la ou on se situe... 5 pour la recherche, 8 pour les archives, etc.

Pour y parvenir, il y a 2 possibilités, installer une extension ou créer une fonction dans le thème.

  • L'extension a l'avantage d'être configurable depuis la console d'administration, le défaut c'est qu'on charge un peu plus de choses dans ... Et puis pourquoi mettre personnalisable quelque chose de statique dans la vie de tous les jours...
  • La deuxième méthode consiste à placer une fonction directement dans le fichier functions.php de votre thème. Cette fonction sera associée au filtre "pre_get_posts" de WordPress.

Fonction d'exemple:

add_filter( 'pre_get_posts', 'quantity_per_view' );
function quantity_per_view( $wp_query = '' ) {
	if ( is_search() ) { // recherche
		$wp_query->query_vars['posts_per_page'] = 9;
	} elseif ( is_category() ) { // Category
		$wp_query->query_vars['posts_per_page'] = 8;
	} elseif ( is_tag() ) { // Tag
		$wp_query->query_vars['posts_per_page'] = 8;
	} elseif ( is_author() ) { // Auteur
		$wp_query->query_vars['posts_per_page'] = 8;
	} elseif ( is_date() ) { // Archive
		$wp_query->query_vars['posts_per_page'] = 8;
	}

	return $wp_query;
}

Ici, on permet de spécifier une quantité différente pour la vue, les catégories, les tags, les auteurs et les archives... La valeur que vous fixerez écrasera l'option présente dans la page de réglages "Lecture" de WordPress.

Je conclurai en disant que cette méthodologie est l'unique bonne méthode pour spécifier le nombre d'articles par page. Utilise la fonction query_posts() est une aberration digne de tout bon webdesigner en herbe pour la simple et bonne raison que vous effectuerez le double de requête SQL...

Cela aura comme conséquence d'augmenter la charge serveur et le temps de génération des pages ;) Si les créateurs de thèmes magazine US (Mimbo et ses petits cousins) me lisent (ce qui est compliqué), prenez de la graine !

57 Commentaires

  1. Merci pour la fonction, ça va pouvoir me servir :-)

  2. « Utilise la fonction query_posts() est une aberration digne de tout bon webdesigner en herbe »

    Je sais pas pourquoi mais je me sens visé par cette remarque !! :D

    Mais cela dit, je suis d’accord, utiliser les queries uniquement pour changer le nombre d’articles à afficher est idiot !! On ne m’y reprendra plus…….. jusqu’à la prochaine fois !! :P

  3. @ Francis » Pas de raison de te sentir visé, je pense que pratiquement tout le monde balance du query_post() dans ses thèmes et Amo souligne à juste titre pourquoi c’est une mauvaise pratique.

    @ Amo » Un excellent post ici qui mérite de devenir une référence ! Peux-tu nous préciser le pourquoi du
    !is_category(1)
    de ton exemple ? La catégorie d’id 1 a-t-elle quelque chose de spécial ?

    (Autre chose qui n’a rien à voir, mais le système de création automatique de lien sur chaque mot correspondant à un tag me semble plus générateur de bruit que porteur d’une vraie valeur ajoutée pour tes lecteurs – mon avis personnel, bien sûr !)

  4. C’est bien la peine que je mette des balises >strong< dans mon commentaire !

  5. Francis > Ca n’est pas pour toi. Tu n’a pas créer Mimbo ;)

    CuI > Euh, en fait cette condition n’a rien à foutre dans cet exemple, c’est pour les besoin de WP-FR ;) (code updated)

    Pour les tags, je suis d’accord avec toi, ca ne sert pas à grand chose, mais honnêtement HWM est mon labo, je dev sur Simple Tags direct sur mon blog, d’ou la raison pourquoi ils sont activés ;)

  6. Voilà le genre d’article que l’on aimerait lire plus souvent. Quelques lignes simples et propres pour régler un vrai problème. Et un rappel sur le fait qu’un thème mal codé peut dégrader terriblement les performances de WordPress. Attention donc avant de se précipiter sur un thème « super bôooo », d’autant qu’on va rarement regarder comment il est « fabriqué »…

  7. Bizarre, je ne reçois pas les updates par email alors que j’y suis abonné… Enfin bon, tout ça pour dire qu’il est grand temps que je me mette au php, ras le bol d’être limité à ce niveau-là !! :D … maintenant, va falloir trouver le temps…

  8. Pingback : LbSquat » Blog Archive » LbSquat is back!!

  9. Merci beaucoup pour cette petite fonction vraiment très pratique.

  10. Francis > Pour les notifications mail, c’est corrigé ;)

  11. S@lut Amaury (et salut aux autres aussi bien sur),
    Merci pour cette fonction très pratique,je cherche à faire quelque chose de similaire à cause du sticky. C’est à dire que j’aimerais sur l’accueil qu’il y ait 4 posts qui s’affichent et 6 sur les pages suivantes. J’imagine qu’avec ta fonction c’est possible, non?
    P.S : Désolé pour le commentaire précédent foiré (il est tôt), tu peux le supprimer sans souci :D

    Didier.

  12. Bonjour ! Et merci pour cette solution qui semble fonctionner à merveille. Une petite question : comment fait-on pour régler l’affichage sur une page en particulier avec cette fonction ? Je veux par exemple avoir un nb de billets, et ceux de quelques catégories seulement.

    A partir du code ci-dessus, j’ai tenté :

    } elseif ( is_page('annonces') ) { // Annonces
    $wp_query->query_vars['posts_per_page'] = 3;
    $wp_query->query_vars['cat'] = 52,54,55;

    Apparemment, ça ne fonctionne pas. J’ai été alors obligé d’utiliser le query_posts dans cette page annonces pour avoir ce que je voulais, mais voilà, la pagination page 1, page 2, etc, ne fonctionne pas. Bref, je tourne en rond ! Si quelqu’un a une lumière. Même dans le livre WordPress du trio Francis-Xavier-Amaury, je n’ai pas trouvé. Il faut dire que je suis encore débutant en WP ;-)
    Mais là, je sèche, même avec l’excellent livre WordPress écrit par le trio Francis-Xavier-Amaury.

  13. Euh, là, j’en ai fait un peu trop sur le livre. Un copier coller trop rapide. Ca fait de la pub à bon compte… ;-)

  14. Wolforg > Tu as essayé ca :
    add_filter( ‘pre_get_posts’, ‘quantity_per_view’ );
    function quantity_per_view( $wp_query =  » ) {
    global $paged;
    if ( is_home() || $paged < = 1 ) { // home, page 1 $wp_query->query_vars[‘posts_per_page’] = 4;
    } elseif( is_home() ) { // Home page ++
    $wp_query->query_vars[‘posts_per_page’] = 6;
    }
    }

  15. Stéphan > Pourquoi ne pas avoir simplement fait une catégorie à la place d’une page ? (et éventuellement avec un query_posts(), appeler le contenu de la page Annonces ?

  16. S@lut Amaury et merci de ta réponse :)
    Je viens d’essayer ta modif’, mais cela me fournit un superbe « Parse error: syntax error, unexpected ‘=’ in /homepages/34/d140709433/htdocs/ail/wp-content/themes/chameleon_1-1/functions.php on line 193 ». La ligne 193 correspondant à :
    if ( is_home() || $paged < = 1 ) { // home, page 1
    Ettonant, non? ;-)

  17. Il ne faut pas faire de copier/coller depuis les commentaires ;)

  18. Salut Amaury !

    J’ai opté pour la page plus que pour la catégorie parce que je souhaite intégrer en bout de liste un formulaire pour passer une annonce. Il ne me semblait pas possible de le faire sur une page Catégorie. J’utilise Contact Form 7. Et puis, si je ne me trompe pas, l’usage du query_posts posera quand même problème pour la nav sur la page de la catégorie concernée, non ?

  19. Salut,
    Pour moi c’est pas jojo, effectivement ça fait ce que je demande, mais ça me crée 2 erreurs java sous IE, et ça me bloque carrément le site sous firefox!
    Piti problème! Dommage :(

  20. Ne pas faire de copier coller bête depuis ici, en général les quotes sont déformés…

  21. Tiens j’ai retenté, ça marche :)
    Merci beaucoup!

  22. Bonjour Amaury,

    J’ai utilisé cette fonction qui et vraiment géniale mais je m’aperçois qu’elle n’est pas prise en compte dès lors que j’utilise la réécriture des permaliens sous forme de /%category%/%postname%
    Est-ce qu’il existe une solution ou suis-je obligé d’utiliser la forme d’url par défaut ?

    Merci.

  23. J’utilise ce format de réécriture sur les sites ou je travaille et je n’ai aucun problème avec la limite du nombre d’articles…

    Toi ca buggue dès que tu actives les permaliens ? (tout format ?)

  24. Bonjour Amaury,
    tu as raison, ta fonction marche parfaitement bien avec tous les permaliens.
    C’est en fait mon utilisation de ta fonction qui ne marche pas.
    En fait je voudrais afficher un nombre d’articles différent selon les categories.
    ce qui donne ça :

    query_vars[‘posts_per_page’] = 4;
    } elseif ( is_category(‘journal’) ) { // catégorie nommée ‘journal’
    $wp_query->query_vars[‘posts_per_page’] = 6;
    } elseif ( is_category() ) { // Les autres catégories
    $wp_query->query_vars[‘posts_per_page’] = 8;
    }
    return $wp_query;
    }
    ?>

    Cette fonction marche très bien si les permaliens ont la forme par défaut, en revanche ça ne fonctionne plus si on passe à une autre forme de permaliens.

    Il y a surement une erreur dans ma manière de coder.
    Je te remercie pour ta réponse et pour ton blog en général :-)

  25. Je te remets la fonction telle que je l’utilise, elle n’est pas bien passée dans le 1er message

    add_filter( ‘pre_get_posts’, ‘quantity_per_view’ );
    function quantity_per_view( $wp_query =  » ) {
    if ( is_category(‘news’) ) { // catégorie nommée ‘news’
    $wp_query->query_vars[‘posts_per_page’] = 4;
    } elseif ( is_category(‘journal’) ) { // catégorie nommée ‘journal’
    $wp_query->query_vars[‘posts_per_page’] = 6;
    } elseif ( is_category() ) { // Les autres catégories
    $wp_query->query_vars[‘posts_per_page’] = 8;
    }
    return $wp_query;
    }

  26. Amaury, je reviens voir par ici car je ne sais pas comment pointer une catégorie pour lui attribuer un nombre particulier d’articles à afficher.
    if ( is_category(’news’) ) ne semble pas fonctionner autrement qu’avec le permalien par défaut.
    Comment puis-je contourner le problème ?

    merci

  27. 10 jours plus tard j’ai toujours mon problème. Je désespère. je ne sais pas pointer une catégorie particulière pour qu’elle n’affiche qu’un certain nombre d’articles :-/

  28. Seb > Il faut travailler avec les ID et non les slugs sur ce hook.

  29. Merci amo pour la réponse mais malheureusement j’ai déjà essayé ça et même avec les id ça ne fonctionne pas à partir du moment où j’utilise une autre forme de permalien que la forme par défaut.
    Avec la forme par défaut, aucun problème, même en utilisant les slug, mais sinon, ça ne marche pas.
    es-tu certain que tu as réussi sur tes sites à déclarer 2 nombres d’articles différents à afficher dans deux catégories différentes avec une forme autre que celle par défaut ?
    Si c’est le cas et sans vouloir abuser j’aimerais bien voir comment tu as codé ça.
    encore merci.

  30. Amaury,

    tout d’abord merci pour tout. Je suis un peu dégouté car j’aimais beaucoup ta fonction mais il semble que je sois un bien piètre développeur car je ne suis pas parvenu à cibler des catégories ni avec les id ni avec les slugs (en tout cas pas en utilisant une autre forme de permalien que celle par défaut). En désespoir de cause, je me suis rabattu sur ce plugin http://www.maxblogpress.com/plugins/dppp/ qui semble fonctionner très bien.

    Si d’aventure tu pouvais vérifier que tu arrives bel et bien à cibler une catégorie, à lui attribuer un nombre d’articles particulier, et tout ça avec une forme de permalien autre que la forme par défaut, je serai heureux de le savoir (ça me confirmerait qu’il faut décidément que j’arrête définitivement toute tentative dans le domaine du php). Si en revanche tu me confirmais le contraire, j’aurais au moins le plaisir de penser que je n’ai pas perdu ces heures en vain :-)
    et si tu allais jusqu’à me dire où se situait l’erreur je crois que je te baiserais les pieds et dresserais illico une statue à ton effigie :-)

  31. Tu as essayé sur le modèle suivant :

    < ?php
    $cat_id = (int) get_query_var('cat');
    $category_name = trim(get_query_var('category_name'));
    
    if ( $cat_id != 0 ) { // If there's a category ID without Permalink
    
    	// Use method with ID
    	
    } elseif ( !empty($category_name) ) { // Use permalink
    
    	if ( stristr($category_name,'/') ) {
    			$category_name = explode('/',$category_name);
    			if ( $category_name[count($category_name)-1] )
    				$category_name = $category_name[count($category_name)-1]; // no trailing slash
    			else
    				$category_name = $category_name[count($category_name)-2]; // there was a trailling slash
    	}
    	
    	// Soit tu testes le slug, soit tu récupères l'ID depuis le slug...
    	$cat = get_term_by('slug', $category_name, 'category', OBJECT, 'display');
    	if ( $cat ) {
    		$cat_id = $cat->term_id;
    	}
    }
    
    if ( $cat_id == 3 ) {
    	global $wp_query;
    	// Blabla ;)
    }
    ?>
  32. 我也准备换成你这样的了!

  33. Après avoir un peu creusé pour comprendre pourquoi le truc donné à Wolforg ne marchait pas, j’ai le plaisir de vous indiquer la soluce !
    Il ne faut pas utiliser global $paged mais $wp_query->query_vars[‘paged’]

    Ça donne ça :

    if ( is_home()) { // home, page 1
    $wp_query->query_vars['posts_per_page'] = ($wp_query->query_vars['paged'] <= 1) ? 7 : 12 ;
    } elseif ( is_search() ) { // recherche

  34. Comme une image > dans ton code, j’imagine que 12 est le nombre d’articles sur la home, mais que représente le 7 s’il te plait ?

  35. @ Sébastien »
    La notation (condition) ? valeur1 : valeur2 se comprend ainsi :
    Si la condition est vraie, retourner valeur1 sinon retourner valeur2.

    Donc, dans mon code, si je suis sur la home, de deux choses l’une : soit je suis sur la 1ère page, dans ce cas j’affiche 7 articles, soit non, et j’en affiche 12.

  36. Comme une image > Ah Ok, oui, excuse-moi, je ne suis pas familier de cette forme de notation.
    Comme tu peux le voir dans les précédents commentaires, j’avais pour ma part essayer à une époque de cibler les catégories pour leur affecter des nombres d’articles différents mais ça ne marchait pas dès lors que mes permaliens étaient personnalisés /%category%/%postname%
    Est-ce que tu as une idée pour résoudre ce problème ?

  37. @cui :
    Ce que je préfère dans la mentalité « Open Source » c’est qu’une question ne reste que très rarement sans réponse ;-)
    C’est plus ou moins rapide selon la question mais comme dirait l’autre « Vieux motard que jamais » :-D
    Merci à toi Jérome donc, et au plaisir de te recroiser (ainsi qu’Amaury) à un prochain Wordcamp :-)

    Ré@gissons, p@rticipons…

  38. J’avoue, Wolforg, que je me suis mis vraiment à chercher que lorsque j’en ai eu besoin ;-) Mais bon, c’est le résultat qui importe.

    Sébastien, j’ai regardé un peu le source de wp-include/query.php, j’ai fait des tests et j’ai réussi, je crois, à trouver un truc qui fonctionne (chez moi, en tout cas) :

    Remplace if (is_category('slug')) par if ($wp_query->query_vars['category_name'] == 'slug')

  39. @ cui : C’est là que réside la grande force du libre, on s’entraide non pas parce que l’on éprouve le besoin d’aider mais plutôt car nos besoins convergent à un moment donné sur un sujet précis, cela s’appelle les réseaux de coopération faibles je crois. Linux s’est monté comme cela et nos politiques seraient bien inspirés de s’en …inspirer justement :-p

  40. @ tous » Je me suis aperçu d’un petit problème quand on utilise un nombre d’articles différents sur la home (mettons qu’on en ait 6 sur la home et 10 sur les autres pages, la page 1 va afficher les articles 1 à 6 et la page 2 les articles 10 à 20, exit donc les article 7 à 9 !
    Il faut donc positionner l’offset.

    Voici donc ce que donne ma fonction après mise au point :
    function cui_quantity_per_view( $wp_query = '' ) {
    //global $paged;
    $nb_home = 7; // Home page
    $nb_def = $wp_query->query_vars['posts_per_page']; // Valeur par défaut, définie dans l'interface (Réglages/Lecture)
    $nb_search = 20; // Search pages

    // Optimiser en regroupant par valeurs identiques une fois les valeurs fixées
    if ( is_home()) { // home, page 1
    $page = absint($wp_query->query_vars['paged']);
    if ($page query_vars['posts_per_page'] = $nb_home ;
    } else {
    $wp_query->query_vars['offset'] = ($page-2) * $nb_def + $nb_home ;
    // $wp_query->query_vars['posts_per_page'] = $nb_def ;
    }
    } elseif ( is_search() ) { // recherche
    $wp_query->query_vars['posts_per_page'] = $nb_search;
    }
    // else : on garde la valeur par défaut

    return $wp_query;
    }

    Dans cet exemple, on utilise pour toutes les pages la valeur par défaut définie dans l’interface WordPress, sauf pour la Home et les résultats de recherche.

  41. Hum… ça s’affiche bizarre. Je reposte la fonction !
    function cui_quantity_per_view( $wp_query = '' ) {
    //global $paged;
    $nb_home = 7; // Home page
    $nb_def = $wp_query->query_vars['posts_per_page']; // Valeur par défaut, définie dans l'interface (Réglages/Lecture)
    $nb_search = 20; // Search pages

    if ( is_home()) { // home, page 1
    $page = absint($wp_query->query_vars['paged']);
    if ($page query_vars['posts_per_page'] = $nb_home ;
    } else {
    $wp_query->query_vars['offset'] = ($page-2) * $nb_def + $nb_home ;
    // $wp_query->query_vars['posts_per_page'] = $nb_def ;
    }
    } elseif ( is_search() ) { // recherche
    $wp_query->query_vars['posts_per_page'] = $nb_search;
    }
    // else : on garde la valeur par défaut

    return $wp_query;
    }

  42. Hop une dernière précision à ce sujet.

    Pour n’affecter qu’une seule fois le requête WP_Query.
    Il suffit de placer la fonction

    remove_filter( ‘pre_get_posts’, ‘quantity_per_view’ );

    A l’intérieur de la fonction quantity_per_view.
    Cela permet d’auto-désactiver la fonction et ainsi on peut utiliser plusieurs fois la méthode query_posts sans aucun problème !

  43. CUI > Si le code passe mal, passe via un service de partage de code ;)

  44. Pingback : One Chapter a Day » Afficher un nombre d’articles différents par page

  45. Je suis d’accord avec Sebastien. il est impossible d’utiliser cette function avec le permaliens /%postname%/
    Quelqu’un at-il une idée?

  46. Pas mal comme astuce ! Ca date un peu mais c’est exactement ce que je cherchais :) Merci beaucoup pour le partage !

  47. Bonjour Amaury,

    J’ai utilisé cette fonction qui et vraiment géniale mais je m’aperçois qu’elle n’est pas prise en compte dès lors que j’utilise la réécriture des permaliens sous forme de /%category%/%postname%
    Est-ce qu’il existe une solution ou suis-je obligé d’utiliser la forme d’url par défaut ?

    Merci.

  48. simple curiosité,on peut utiliser cette méthode pour afficher sur la page d’accueil, 5 articles d’une catégorie,puis 5 articles d’un autre catégorie,etc ..
    merci

  49. Bonjour!

    Sans être une experte en php, j’ai réussi jusqu’à maintenant à opérer de petites modifications en fouinant sur le web et en copiant des bouts de code, ou en lisant attentivement le code lui-même.
    J’ai également toujours fait attention à bien repérer où je collais, pour éventuellement retirer le bout de code en cas d’échec ou d’inaction.
    J’ai collé votre code en changeant les variables selon mes besoins, et j’ai eu ce message après validation : Parse error: syntax error, unexpected T_ELSEIF in /homez.527/lestoilew/sur-les-chemins/wp-content/themes/sandbox/functions.php on line 93

    J’ai cherché la ligne 93, mais je ne sais pas vraiment compter les lignes dans une page php, ça tombait (selon mon comptage) soit sur la } finale de votre code, soit sur une ligne vide séparant deux codes différents, j’ai retiré le code, l’ai placé à un autre endroit du fichier et validé => même message

    De retour sur mon blog, j’ai cliqué au hasard pour voir ce qu’il se passait => même message

    Je me suis dit « oops », puis « ok, je vais aller chercher ma sauvegarde du fichier functions.php et la copier direct dans mon admin, sauf que où que je clique, toujours ce même message.

    En résumé, blog inaccessible …

    Je suis allée chercher le fichier sur mon ordi et l’ai rebalancé via filezilla : ouf, tout va bien, mais du coup, je n’ose pas re-tenter l’expérience de votre code qui pourtant répondait e-xac-te-ment à ma recherche (j’aimerais éviter de cumuler les extensions).

    Avez-vous une idée de ce qui a pu se passer?

    Merci, et belle journée à vous!

  50. il est déconseillé de passer par l’éditeur de WordPress pour faire ce genre d’opération,il est préférable d’ouvrir le fichier avec un éditeur de texte comme notepad++ ,rajouter le code ou le modifier puis l’envoyer par FileZilla.
    Comme on personnalisé u thème,il est préférable de créer un thème enfant,il y a un article sur wpchannel à ce sujet.
    Votre thème date de 2009,était-il compatible????

  51. Bonjour et merci pour cette réponse :)

    Pour le thème enfant, j’ai tenté plusieurs fois d’en créer un et je n’y parviens pas, je ne sais pas pourquoi, alors je sauvegarde « à la main » sur les fichiers installés dans mon PC à chaque fois que je fais une modif quelque part.

    Sandbox n’est plus d’actualité depuis longtemps, c’est vrai, mais j’aime vraiment sa flexibilité totale et ce que j’ai réussi à en tirer à l’époque. Je ne me sens pas le courage, et je n’ai pas le temps, de reprendre intégralement un autre thème ….

    J’ai laissé tomber l’idée de coder pour cette fonction spécifique décrite ici, j’ai pris le plugin « Posts per page », et puis voilà … :)

    Très beau weekend à vous!

  52. un thème enfant a besoin d’un fichier style.css avec la ligne de code qui appelle le fichier style.css du thème parent.

    Petit à petit les thèmes se tournent vers le système Responsive,thème qui s’adapte si on voit un site sur un pc,une tablette numérique ou un smartphone.

    Pensez à être sous WP3.4.1 !!!!

  53. Bonjour,

    Deux jours que je cherche comment résoudre mon problème pourtant simple : faire en sorte que la page d'accueil affiche un article complet, mais que les catégories affichent uniquement les titres et une dizaine par page.
    Le query_post, je plussoie, c'est une aberration ! Ca m'a pris des heures pour essayer de régler ça correctement, et deux minutes avec votre solution !

    Bref, un grand merci !

Laisser un commentaire

Champs Requis *.