Problem
Domyślnie w dowolnym kontekście WordPress używa głównego zapytania do ustalenia podziału na strony. Główny obiekt zapytania jest przechowywany w $wp_query
globalnym, który służy również do wyprowadzania głównej pętli zapytania:
if ( have_posts() ) : while ( have_posts() ) : the_post();
Po użyciu zapytania niestandardowego , należy utworzyć całkowicie odrębny przedmiot zapytania:
$custom_query = new WP_Query( $custom_query_args );
I to zapytanie jest generowane przez całkowicie oddzielną pętlę:
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
Ale znaczniki szablonów stronicowanie, w tym previous_posts_link()
, next_posts_link()
, posts_nav_link()
, i paginate_links()
, opierają swoje wyjście na główny obiekt zapytania , $wp_query
. To główne zapytanie może, ale nie musi, być paginowane. Jeśli bieżącym kontekstem jest na przykład niestandardowy szablon strony, główny $wp_query
obiekt będzie składał się tylko z jednego posta - identyfikatora strony, do której przypisany jest niestandardowy szablon strony.
Jeśli bieżącym kontekstem jest pewnego rodzaju indeks archiwalny, główny $wp_query
może składać się z wystarczającej liczby postów, aby spowodować podział na strony, co prowadzi do następnej części problemu: dla głównego $wp_query
obiektu WordPress przekaże paged
parametr do zapytania na podstawie paged
Zmienna zapytania URL. Po pobraniu zapytania paged
parametr ten zostanie użyty do ustalenia, który zestaw stronicowanych postów ma zostać zwrócony. Jeśli kliknięty zostanie wyświetlony link do stronicowania, a następna strona zostanie załadowana, zapytanie niestandardowe nie będzie w żaden sposób wiedziało, że podział stronicowania się zmienił .
Rozwiązanie
Przekazywanie poprawnego parametru stronicowanego do zapytania niestandardowego
Zakładając, że niestandardowe zapytanie korzysta z tablicy args:
$custom_query_args = array(
// Custom query parameters go here
);
Musisz przekazać poprawny paged
parametr do tablicy. Możesz to zrobić, pobierając zmienną zapytania URL używaną do ustalenia bieżącej strony, poprzez get_query_var()
:
get_query_var( 'paged' );
Następnie możesz dołączyć ten parametr do niestandardowej tablicy argumentów zapytania:
$custom_query_args['paged'] = get_query_var( 'paged' )
? get_query_var( 'paged' )
: 1;
Uwaga: jeśli twoja strona jest statyczną stroną główną , pamiętaj, aby używać jej page
zamiast paged
jako statycznej strony głównej, page
a nie paged
. Właśnie to powinieneś mieć dla statycznej strony głównej
$custom_query_args['paged'] = get_query_var( 'page' )
? get_query_var( 'page' )
: 1;
Teraz po pobraniu niestandardowego zapytania zostanie zwrócony prawidłowy zestaw stronicowanych postów.
Korzystanie z niestandardowego obiektu zapytania dla funkcji paginacji
Aby funkcje stronicowania dawały prawidłowe dane wyjściowe - tj. Linki poprzedni / następny / stron w stosunku do niestandardowego zapytania - WordPress musi zostać zmuszony do rozpoznania niestandardowego zapytania. Wymaga to trochę „włamania”: zastąpienie głównego $wp_query
obiektu niestandardowym obiektem zapytania $custom_query
:
Włam się do głównego obiektu zapytania
- Wykonaj kopię zapasową głównego obiektu zapytania:
$temp_query = $wp_query
- Null główny obiekt zapytania:
$wp_query = NULL;
Zamień niestandardowe zapytanie na główny obiekt zapytania: $wp_query = $custom_query;
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $custom_query;
Ten „hack” należy wykonać przed wywołaniem jakichkolwiek funkcji stronicowania
Zresetuj główny obiekt zapytania
Po wygenerowaniu funkcji podziału na strony zresetuj główny obiekt zapytania:
$wp_query = NULL;
$wp_query = $temp_query;
Poprawki funkcji paginacji
previous_posts_link()
Funkcja będzie działać normalnie, niezależnie od paginacji. Określa tylko bieżącą stronę, a następnie wyświetla link do page - 1
. Jednak next_posts_link()
do poprawnego wydrukowania jest wymagana poprawka . Jest tak, ponieważ next_posts_link()
używa max_num_pages
parametru:
<?php next_posts_link( $label , $max_pages ); ?>
Podobnie jak w przypadku innych parametrów zapytania, funkcja będzie domyślnie używana max_num_pages
dla głównego $wp_query
obiektu. Aby wymusić next_posts_link()
rozliczenie $custom_query
obiektu, musisz przekazać max_num_pages
funkcję. Możesz pobrać tę wartość z $custom_query
obiektu $custom_query->max_num_pages
:
<?php next_posts_link( 'Older Posts' , $custom_query->max_num_pages ); ?>
Kładąc wszystko razem
Oto podstawowa konstrukcja niestandardowej pętli zapytań z poprawnie działającymi funkcjami paginacji:
// 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;
Dodatek: Co powiesz na query_posts()
?
query_posts()
dla pętli wtórnych
Jeśli używasz query_posts()
do wygenerowania niestandardowej pętli, zamiast tworzenia instancji oddzielnego obiektu dla niestandardowego zapytania za pośrednictwem WP_Query()
, to masz _doing_it_wrong()
i napotkasz kilka problemów ( z których przynajmniej będą problemy z paginacją). Pierwszym krokiem do rozwiązania tych problemów będzie konwersja niewłaściwego użycia query_posts()
na prawidłowe WP_Query()
połączenie.
Używanie query_posts()
do modyfikowania głównej pętli
Jeśli chcesz jedynie zmodyfikować parametry zapytania w głównej pętli - na przykład zmienić posty na stronie lub wykluczyć kategorię - możesz mieć ochotę użyć query_posts()
. Ale nadal nie powinieneś. Kiedy używasz query_posts()
, zmuszasz WordPress do zastąpienia głównego obiektu zapytania. (WordPress faktycznie wykonuje drugie zapytanie i zastępuje $wp_query
.) Problem polega jednak na tym, że zastępuje to zbyt późno w celu zaktualizowania stronicowania.
Rozwiązaniem jest odfiltrowanie głównego zapytania przed pobraniem postów za pomocą pre_get_posts
haka.
Zamiast dodawać to do pliku szablonu kategorii ( category.php
):
query_posts( array(
'posts_per_page' => 5
) );
Dodaj następujące elementy do 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' );
Zamiast dodawać to do pliku szablonu indeksu postów na blogu ( home.php
):
query_posts( array(
'cat' => '-5'
) );
Dodaj następujące elementy do 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' );
W ten sposób WordPress użyje już zmodyfikowanego $wp_query
obiektu podczas określania stronicowania, bez konieczności modyfikacji szablonu.
Kiedy używać jakiej funkcji
Badania na to pytanie i odpowiedź i na to pytanie i odpowiedź , aby zrozumieć, w jaki sposób i kiedy należy używać WP_Query
, pre_get_posts
i query_posts()
.