Masalah
Secara default, dalam konteks apa pun yang diberikan, WordPress menggunakan kueri utama untuk menentukan pagination. Objek kueri utama disimpan di $wp_query
global, yang juga digunakan untuk menampilkan loop kueri utama:
if ( have_posts() ) : while ( have_posts() ) : the_post();
Saat Anda menggunakan kueri khusus , Anda membuat objek kueri yang sepenuhnya terpisah:
$custom_query = new WP_Query( $custom_query_args );
Dan permintaan itu adalah output melalui loop yang sepenuhnya terpisah:
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
Tapi tag pagination Template, termasuk previous_posts_link()
, next_posts_link()
, posts_nav_link()
, dan paginate_links()
, mendasarkan output mereka pada objek query utama , $wp_query
. Kueri utama itu mungkin atau mungkin tidak paginasi. Jika konteks saat ini adalah templat halaman kustom, misalnya, $wp_query
objek utama hanya akan terdiri dari satu posting - ID dari halaman di mana templat halaman kustom ditugaskan.
Jika konteks saat ini adalah semacam indeks arsip, utama $wp_query
mungkin terdiri dari cukup banyak posting yang menyebabkan pagination, yang mengarah ke bagian selanjutnya dari masalah: untuk $wp_query
objek utama , WordPress akan mengirimkan paged
parameter ke kueri, berdasarkan pada paged
Variabel kueri URL. Ketika kueri diambil, paged
parameter itu akan digunakan untuk menentukan set posting paginasi mana yang akan dikembalikan. Jika tautan pagination yang ditampilkan diklik, dan halaman berikutnya dimuat, permintaan khusus Anda tidak akan mengetahui bahwa pagination telah berubah .
Solusinya
Melewati Parameter Paged yang Benar ke Permintaan Kustom
Dengan asumsi bahwa kueri khusus menggunakan array args:
$custom_query_args = array(
// Custom query parameters go here
);
Anda harus meneruskan paged
parameter yang benar ke array. Anda dapat melakukannya dengan mengambil variabel kueri URL yang digunakan untuk menentukan halaman saat ini, melalui get_query_var()
:
get_query_var( 'paged' );
Anda kemudian dapat menambahkan parameter itu ke array args kueri khusus:
$custom_query_args['paged'] = get_query_var( 'paged' )
? get_query_var( 'paged' )
: 1;
Catatan: Jika halaman Anda adalah halaman depan statis , pastikan untuk menggunakan page
bukan paged
sebagai halaman depan statis gunakan page
dan tidak paged
. Inilah yang harus Anda miliki untuk halaman depan statis
$custom_query_args['paged'] = get_query_var( 'page' )
? get_query_var( 'page' )
: 1;
Sekarang, ketika kueri khusus diambil, kumpulan kiriman paginasi yang benar akan dikembalikan.
Menggunakan Objek Kueri Kustom untuk Fungsi Pagination
Agar fungsi pagination dapat menghasilkan output yang benar - yaitu tautan sebelumnya / berikutnya / halaman relatif terhadap permintaan khusus - WordPress harus dipaksa untuk mengenali permintaan khusus. Hal ini memerlukan sedikit "hack": mengganti utama $wp_query
objek dengan objek query kustom, $custom_query
:
Meretas objek permintaan utama
- Cadangkan objek permintaan utama:
$temp_query = $wp_query
- Null objek permintaan utama:
$wp_query = NULL;
Tukar kueri khusus ke objek kueri utama: $wp_query = $custom_query;
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $custom_query;
"Retasan" ini harus dilakukan sebelum memanggil fungsi pagination
Setel ulang objek kueri utama
Setelah fungsi pagination telah di-output, reset objek query utama:
$wp_query = NULL;
$wp_query = $temp_query;
Perbaikan Fungsi Pagination
The previous_posts_link()
fungsi akan bekerja secara normal, terlepas dari pagination. Ini hanya menentukan halaman saat ini, dan kemudian menampilkan tautan untuk page - 1
. Namun, perbaikan diperlukan untuk next_posts_link()
menghasilkan dengan benar. Ini karena next_posts_link()
menggunakan max_num_pages
parameter:
<?php next_posts_link( $label , $max_pages ); ?>
Seperti parameter kueri lainnya, secara default fungsi akan digunakan max_num_pages
untuk $wp_query
objek utama . Untuk memaksa next_posts_link()
untuk memperhitungkan $custom_query
objek, Anda harus meneruskan max_num_pages
ke fungsi. Anda dapat mengambil nilai ini dari $custom_query
objek $custom_query->max_num_pages
::
<?php next_posts_link( 'Older Posts' , $custom_query->max_num_pages ); ?>
Menyatukan semuanya
Berikut ini adalah konstruksi dasar dari loop kueri khusus dengan fungsi pagination yang berfungsi dengan baik:
// 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;
Tambahan: Bagaimana query_posts()
?
query_posts()
untuk Loop Sekunder
Jika Anda menggunakan query_posts()
untuk menghasilkan loop kustom, alih-alih instantiating objek terpisah untuk permintaan kustom melalui WP_Query()
, maka Anda _doing_it_wrong()
, dan akan mengalami beberapa masalah (tidak sedikit yang akan menjadi masalah pagination). Langkah pertama untuk menyelesaikan masalah-masalah tersebut adalah mengonversi penggunaan yang tidak query_posts()
tepat menjadi WP_Query()
panggilan yang tepat .
Menggunakan query_posts()
untuk Memodifikasi Loop Utama
Jika Anda hanya ingin mengubah parameter untuk kueri loop utama - seperti mengubah posting per halaman, atau mengecualikan kategori - Anda mungkin tergoda untuk menggunakannya query_posts()
. Tapi kamu tetap tidak seharusnya. Saat Anda menggunakan query_posts()
, Anda memaksa WordPress untuk mengganti objek permintaan utama. (WordPress benar-benar membuat kueri kedua, dan menimpa $wp_query
.) Masalahnya, meskipun, ia melakukan penggantian ini terlambat dalam proses untuk memperbarui pagination.
Solusinya adalah dengan memfilter permintaan utama sebelum posting diambil , melalui pre_get_posts
hook.
Alih-alih menambahkan ini ke file templat kategori ( category.php
):
query_posts( array(
'posts_per_page' => 5
) );
Tambahkan yang berikut ke 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' );
Alih-alih menambahkan ini ke file template indeks posting blog ( home.php
):
query_posts( array(
'cat' => '-5'
) );
Tambahkan yang berikut ke 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' );
Dengan begitu, WordPress akan menggunakan objek yang sudah dimodifikasi $wp_query
saat menentukan pagination, tanpa perlu modifikasi templat.
Kapan harus menggunakan fungsi apa
Penelitian pertanyaan ini dan jawaban dan pertanyaan dan jawaban untuk memahami bagaimana dan kapan menggunakan WP_Query
, pre_get_posts
dan query_posts()
.