Il problema
Per impostazione predefinita, in qualsiasi contesto, WordPress utilizza la query principale per determinare l'impaginazione. L'oggetto query principale è archiviato nel $wp_query
globale, che viene anche utilizzato per generare il ciclo di query principale:
if ( have_posts() ) : while ( have_posts() ) : the_post();
Quando si utilizza una query personalizzata , si crea un oggetto query completamente separato:
$custom_query = new WP_Query( $custom_query_args );
E quella query viene emessa tramite un ciclo completamente separato:
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
Ma i tag modello di impaginazione, tra cui previous_posts_link()
, next_posts_link()
, posts_nav_link()
, e paginate_links()
, basano la loro uscita sul oggetto query principale , $wp_query
. Quella query principale può o non può essere impaginata. Se il contesto corrente è un modello di pagina personalizzato, ad esempio, l' $wp_query
oggetto principale sarà costituito da un solo post : quello dell'ID della pagina a cui è assegnato il modello di pagina personalizzato.
Se il contesto corrente è un indice di archivio di qualche tipo, il principale $wp_query
può essere costituito da post sufficienti per causare l'impaginazione, il che porta alla parte successiva del problema: per l' $wp_query
oggetto principale , WordPress passerà un paged
parametro alla query, in base al paged
Variabile di query URL. Quando la query viene recuperata, quel paged
parametro verrà utilizzato per determinare quale set di post impaginati da restituire. Se si fa clic su un collegamento di impaginazione visualizzato e viene caricata la pagina successiva, la query personalizzata non avrà modo di sapere che l'impaginazione è cambiata .
La soluzione
Passando il parametro impaginato corretto alla query personalizzata
Supponendo che la query personalizzata utilizzi un array args:
$custom_query_args = array(
// Custom query parameters go here
);
Sarà necessario passare il paged
parametro corretto all'array. Puoi farlo recuperando la variabile della query URL utilizzata per determinare la pagina corrente, tramite get_query_var()
:
get_query_var( 'paged' );
È quindi possibile aggiungere quel parametro alla matrice di args query personalizzata:
$custom_query_args['paged'] = get_query_var( 'paged' )
? get_query_var( 'paged' )
: 1;
Nota: se la tua pagina è una prima pagina statica , assicurati di utilizzare page
invece di paged
come usa una prima pagina statica page
e non paged
. Questo è ciò che dovresti avere per una prima pagina statica
$custom_query_args['paged'] = get_query_var( 'page' )
? get_query_var( 'page' )
: 1;
Ora, quando viene recuperata la query personalizzata, verrà restituito il set corretto di post impaginati.
Utilizzo dell'oggetto query personalizzato per le funzioni di impaginazione
Affinché le funzioni di impaginazione producano l'output corretto, ovvero i collegamenti precedente / successivo / della pagina relativi alla query personalizzata, WordPress deve essere costretto a riconoscere la query personalizzata. Ciò richiede un po 'di un "hack": la sostituzione del principale $wp_query
oggetto con l'oggetto query personalizzata, $custom_query
:
Hack l'oggetto di query principale
- Eseguire il backup dell'oggetto query principale:
$temp_query = $wp_query
- Annullare l'oggetto query principale:
$wp_query = NULL;
Scambia la query personalizzata nell'oggetto query principale: $wp_query = $custom_query;
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $custom_query;
Questo "hack" deve essere eseguito prima di chiamare qualsiasi funzione di impaginazione
Reimpostare l'oggetto query principale
Una volta emesse le funzioni di impaginazione, reimpostare l'oggetto query principale:
$wp_query = NULL;
$wp_query = $temp_query;
Correzioni della funzione di impaginazione
La previous_posts_link()
funzione funzionerà normalmente, indipendentemente dall'impaginazione. Determina semplicemente la pagina corrente e quindi genera il collegamento per page - 1
. Tuttavia, è necessaria una correzione per next_posts_link()
l'output corretto. Questo perché next_posts_link()
utilizza il max_num_pages
parametro:
<?php next_posts_link( $label , $max_pages ); ?>
Come con altri parametri di query, per impostazione predefinita la funzione utilizzerà max_num_pages
per l' $wp_query
oggetto principale . Per forzare la next_posts_link()
contabilizzazione $custom_query
dell'oggetto, dovrai passare max_num_pages
alla funzione. È possibile recuperare questo valore $custom_query
dall'oggetto $custom_query->max_num_pages
::
<?php next_posts_link( 'Older Posts' , $custom_query->max_num_pages ); ?>
Mettere tutto insieme
Di seguito è riportato un costrutto di base di un ciclo di query personalizzato con funzioni di impaginazione correttamente funzionanti:
// Define custom query parameters
$custom_query_args = array( /* Parameters go here */ );
// Get current page and append to custom query parameters array
$custom_query_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// Instantiate custom query
$custom_query = new WP_Query( $custom_query_args );
// Pagination fix
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $custom_query;
// Output custom query loop
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
// Loop output goes here
endwhile;
endif;
// Reset postdata
wp_reset_postdata();
// Custom query loop pagination
previous_posts_link( 'Older Posts' );
next_posts_link( 'Newer Posts', $custom_query->max_num_pages );
// Reset main query object
$wp_query = NULL;
$wp_query = $temp_query;
Addendum: che dire query_posts()
?
query_posts()
per loop secondari
Se stai usando query_posts()
per generare un ciclo personalizzato, piuttosto che creare un'istanza di un oggetto separato per la query personalizzata tramite WP_Query()
, allora sei _doing_it_wrong()
, e incontrerai diversi problemi (non ultimo i problemi di impaginazione). Il primo passo per risolvere questi problemi sarà convertire l'uso improprio query_posts()
in una WP_Query()
chiamata corretta .
Utilizzo query_posts()
per modificare il loop principale
Se desideri semplicemente modificare i parametri per la query del ciclo principale , ad esempio modificando i post per pagina o escludendo una categoria, potresti essere tentato di utilizzare query_posts()
. Ma non dovresti ancora. Quando si utilizza query_posts()
, si forza WordPress a sostituire l'oggetto query principale. (WordPress in realtà esegue una seconda query e sovrascrive $wp_query
.) Il problema, tuttavia, è che esegue questa sostituzione troppo tardi nel processo per aggiornare l'impaginazione.
La soluzione è di filtrare la query principale prima che i post vengano recuperati , tramite l' pre_get_posts
hook.
Invece di aggiungere questo al file modello categoria ( category.php
):
query_posts( array(
'posts_per_page' => 5
) );
Aggiungi quanto segue a functions.php
:
function wpse120407_pre_get_posts( $query ) {
// Test for category archive index
// and ensure that the query is the main query
// and not a secondary query (such as a nav menu
// or recent posts widget output, etc.
if ( is_category() && $query->is_main_query() ) {
// Modify posts per page
$query->set( 'posts_per_page', 5 );
}
}
add_action( 'pre_get_posts', 'wpse120407_pre_get_posts' );
Invece di aggiungere questo al file modello indice dei post di blog ( home.php
):
query_posts( array(
'cat' => '-5'
) );
Aggiungi quanto segue a functions.php
:
function wpse120407_pre_get_posts( $query ) {
// Test for main blog posts index
// and ensure that the query is the main query
// and not a secondary query (such as a nav menu
// or recent posts widget output, etc.
if ( is_home() && $query->is_main_query() ) {
// Exclude category ID 5
$query->set( 'category__not_in', array( 5 ) );
}
}
add_action( 'pre_get_posts', 'wpse120407_pre_get_posts' );
In questo modo, WordPress utilizzerà l' $wp_query
oggetto già modificato durante la determinazione dell'impaginazione, senza che sia necessario modificare il modello.
Quando utilizzare quale funzione
La ricerca questa domanda e risposta e questa domanda e risposta per capire come e quando usare WP_Query
, pre_get_posts
e query_posts()
.