Wanneer je het aantal blogposts wilt beperken wat er op een pagina getoond wordt, dan is dat heel makkelijk te doen vanuit de WordPress instellingen. Je gaat gewoon naar ‘Instellingen->Lezen’ en onder het aantal te tonen berichten, pas je de instelling gewoon aan :
Makkelijk genoeg niet waar? Daar heb je geen code snippet voor nodig.
Wat er alleen niet duidelijk wordt aangegeven, is dat je hiermee ook alle custom post types die je elders zou willen gebruiken ingesteld hebt.
Heb je bijvoorbeeld nog een ‘portfolio’, ’testimonials’, ‘products’ en ‘faq’ custom post types zullen die ook allemaal tot dat aantal beperkt worden op archief pagina’s.
Dat is misschien niet wat je wilt. Ik kan mij bijvoorbeeld voorstellen, dat je een blog, een webshop en een portfolio van de door jou uitgevoerde projecten hebt. De blogpagina, waarbij je iedere blogpost op één rij van de pagina hebt, wil je niet te lang maken, en daarom zou je graag 5 blogposts per pagina zien. Voor wat betreft de portfolio, met foto’s van je projecten, wil je eigenlijk alles in een matrix van 5 rijen van 4 kolommen zetten (20 posts dus) en je winkelproducten wil je 12 per pagina tonen. Een matrix van 3×4. Hoe krijg je dit voor elkaar?
Theme builders zijn hier niet je vriend!
Wanneer je een theme builder als Elementor Pro gebruikt, dan lijkt de eerste oplossing om in plaats van de Archive Widget (die je op de archive pagina gebruikt, om posts te tonen, en waarbij je geen maximaal aantal posts in kan stellen) de ‘Posts Widget’ te gebruiken. Die kan je op iedere pagina gebruiken, en daar kan je wel een maximum aantal per pagina instellen.
Probleem opgelost. Of toch niet?
Niet dus. Want wanneer je dit doet, dan ga je wel heel onvoorzichtig met je resources om. Wat gebeurt er namelijk op een archief pagina? Zodra deze pagina geopend wordt, zal WordPress automatisch vragen om de eerste x posts voor die pagina. De ‘Archive Widget’ zal vervolgens deze ‘opgevraagde posts’ op het scherm tonen.
Wanneer je een Elementor Pro ‘Posts’ widget gebruikt, dan zal dezelfde vraag nog een keer worden gesteld. Of met andere woorden, een ‘dure’ query zal tweemaal uitgevoerd worden, en dat komt je performance niet ten goede.
Bovendien, omdat de posts getoond in een post widget geen deel uitmaken van de archive page, zal geen enkele code snippet die je hier kan vinden en bedoeld is voor archive pages ook maar enige invloed hebben op de getoonde gegevens. Ook iets belangrijks om rekening mee te houden.
Wanneer we dit op willen lossen, doen we dit op de meest betrouwbare en snelste manier: Een code snippet.
De usecase
In de code gebruik ik de post types en de aantallen die ik aan het begin van dit artikel heb genoemd. Denk erom om in jouw eigen code de namen en aantallen aan te passen aan jouw eigen situatie.
<?php
add_filter( 'pre_get_posts', 'wxp_portfolio_posts_per_page' );
function wxp_portfolio_posts_per_page($query) {
if ( $query->is_post_type_archive( 'portfolio' ) && ! is_admin() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '20' );
}
return $query;
}
In het bovenstaande voorbeeld hebben we dit gedaan voor één post type. Het ‘portfolio’ type. Waarom niet voor de blogposts (‘post’ type) ook?
Waarom wel? We kunnen immers voor één post type de ingestelde default aanhouden. Wanneer we onder ‘Instellingen->Lezen’ het aantal op ‘6’ zetten zal voor ieder post type wat geen portfolio is de default behouden blijven. Daarnaast geeft de tekst op de instellingen pagina aan, dat je het aantal blogposts instelt. Wanneer je deze code voor een klant gebruikt, wil je in ieder geval verwarring voorkomen, en dus zorg je dat dit aantal nog steeds aangeeft, hoeveel blogposts getoond zullen worden.
Een ander post type wat we op deze manier willen beperken is het ‘product’ post type. We kunnen nu twee dingen doen : Voor ieder post type een aparte functie maken, of in één functie alle post typen instellen.
De code hieronder is slechts als voorbeeld bedoeld. Deze code zal niet werken voor het product type. Later in dit artikel leg ik uit waarom.
Eén functie voor alle instellingen
<?php
add_filter( 'pre_get_posts', 'wxp_posts_per_page' );
function wxp_posts_per_page($query) {
if ( $query->is_post_type_archive( 'portfolio' ) && ! is_admin() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '20' );
}
if ( $query->is_post_type_archive( 'product' ) && ! is_admin() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '12' );
}
return $query;
}
Ik heb hier dus de functie hernoemd van ‘wxp_portfolio_posts_per_page’ naar ‘wxp_posts_per_page’. Omdat de functie nu niet meer specifiek voor portfolio items is. Binnen de functie test ik apart for ieder post type.
Het voordeel van deze wijze van aanpak is dat er slechts één filter functie aangeroepen hoeft te worden. En dit is verreweg de snelste oplossing. Heb je een groot aantal verschillende post types die je in wilt stellen, kies je mogelijk liever voor een overzichtelijke oplossing. Dan is onderstaande code een mogelijkheid. Deze aanpak heeft niet mijn persoonlijke voorkeur.
<?php
add_filter( 'pre_get_posts', 'wxp_portfolio_posts_per_page' );
function wxp_portfolio_posts_per_page($query) {
if ( $query->is_post_type_archive( 'portfolio' ) && ! is_admin() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '20' );
}
return $query;
}
add_filter( 'pre_get_posts', 'wxp_product_posts_per_page' );
function wxp_portfolio_posts_per_page($query) {
if ( $query->is_post_type_archive( 'product' ) && ! is_admin() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '24' );
}
return $query;
}
Maar zoals eerder aangegeven, beide code snippets zullen niet werken voor producten. Om één heel simpele reden: WooCommerce heeft voor het tonen van producten op de ‘Winkel’ pagina een compleet andere functie ontwikkeld. Het resultaat van de ‘pre_get_post’ filter wordt later overschreven door een compleet ander filter. Om het in WooCommerce goed te laten werken, moet je een ander filter gebruiken.
De juiste oplossing
<?php
add_filter( 'loop_shop_per_page', 'wxp_loop_shop_per_page', 20 );
function wxp_loop_shop_per_page( $prods ) {
$prods = 24;
return $prods;
}
De juiste complete code om voor producten en portfolio items het aantal items per pagina in te stellen is dus :
<?php
add_filter( 'pre_get_posts', 'wxp_portfolio_posts_per_page' );
function wxp_portfolio_posts_per_page($query) {
if ( $query->is_post_type_archive( 'portfolio' ) && ! is_admin() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '20' );
}
return $query;
}
add_filter( 'loop_shop_per_page', 'wxp_loop_shop_per_page', 20 );
function wxp_loop_shop_per_page( $prods ) {
$prods = 24;
return $prods;
}