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()
.
paged
nie jest aktualizowany (obv coś wspólnego z administracją- środowiska ajax.php), więc dodałem to:global $paged; $paged = $custom_query_args['paged'];
i zadziałało :)Używam tego kodu do niestandardowej pętli z paginacją:
Źródło:
źródło
Niesamowite jak zawsze Chip. Jako dodatek do tego, rozważ sytuację, w której używasz globalnego szablonu strony dołączonego do strony dla jakiegoś „tekstu wprowadzającego”, a po nim następuje podzapytanie, które chcesz stronicować.
Używając paginate_links () jak wspomniałeś powyżej, z większością domyślnych ustawień (i zakładając, że masz całkiem włączone bezpośrednie linki), twoje linki do stronicowania będą domyślnie ustawione na
mysite.ca/page-slug/page/#
piękne, ale będą zgłaszać404
błędy, ponieważ WordPress nie wie o tej konkretnej strukturze URL i faktycznie poszukaj strony potomnej „strony”, która jest dzieckiem „strony-ślimaka”.Sztuczka polega na tym, aby wstawić fajną regułę przepisywania, która ma zastosowanie tylko do tej konkretnej informacji o stronie „pseudoarchiwum”, która akceptuje
/page/#/
strukturę i przepisuje ją do ciągu zapytania zrozumiałego dla WordPress CAN, a mianowiciemysite.ca/?pagename=page-slug&paged=#
. Uwagapagename
ipaged
niename
ipage
(co spowodowało dosłownie GODZINY żalu, motywując tę odpowiedź tutaj!).Oto reguła przekierowania:
Jak zawsze, zmieniając reguły przepisywania, pamiętaj, aby opróżnić linki bezpośrednie , odwiedzając Ustawienia> Łącza stałe w zapleczu administratora.
Jeśli masz wiele stron, które będą się tak zachowywać (na przykład w przypadku wielu niestandardowych typów postów), możesz chcieć uniknąć tworzenia nowej reguły przepisywania dla każdej strony. Możemy napisać bardziej ogólne wyrażenie regularne, które będzie działać dla każdego identyfikatora strony, który zidentyfikujesz.
Jedno podejście jest poniżej:
Wady / zastrzeżenia
Jedną wadą tego podejścia, która sprawia, że trochę się wymiotuję w ustach jest twarde kodowanie ślimaka strony. Jeśli administrator kiedykolwiek zmieni informacje o stronie tej pseudoarchiwizowanej strony, toast - reguła przepisywania nie będzie już pasować i otrzymasz przerażające 404.
Nie jestem pewien, czy mogę wymyślić obejście tej metody, ale byłoby miło, gdyby to globalny szablon strony w jakiś sposób uruchomił regułę przepisywania. Pewnego dnia mogę ponownie przeczytać tę odpowiedź, jeśli nikt inny nie złamał tego konkretnego orzecha.
źródło
_wp_page_template
, a następnie dodać kolejne reguły przepisywania i czyszczenia.Świetna odpowiedź Chip stworzony dzisiaj musi zostać zmodyfikowany.
Od pewnego czasu mamy
$wp_the_query
zmienną, która powinna być równa$wp_query
globalnej zaraz po wykonaniu głównego zapytania.Oto dlaczego część odpowiedzi Chipa:
nie jest już potrzebny. Możemy zapomnieć o tej części, tworząc zmienną tymczasową.
Teraz możemy zadzwonić:
lub jeszcze lepiej możemy zadzwonić:
Wszystko inne zarysowane chipy zostają. Po tej części dotyczącej resetowania zapytania można wywoływać funkcje podziału na strony
f($wp_query)
, które zależą od$wp_query
globalnego.Aby jeszcze bardziej ulepszyć mechanikę paginacji i dać więcej swobody
query_posts
funkcji, stworzyłem to możliwe ulepszenie:https://core.trac.wordpress.org/ticket/39483
źródło
źródło