Đây là một câu hỏi khá thú vị ( mà tôi đã nêu lên, đặc biệt cho cách tiếp cận và nghiên cứu của bạn ). Đường cong lớn ở đây là trang đầu tiên của truy vấn:
Bạn không thể đặt truy vấn để trả lại 0
bài viết trên trang đầu tiên
Bằng cách di chuyển nội dung trang của mỗi trang lên một trang, bạn sẽ mất trang cuối cùng vì truy vấn sẽ vẫn chỉ có cùng số lượng bài đăng nên $max_num_pages
tài sản sẽ vẫn giữ nguyên
Chúng ta sẽ cần phải "lừa" WP_Query
lớp để trả lại bài đăng của mình một cách chính xác với phần bù của một trang và cũng có được số trang chính xác để không làm mất trang cuối cùng trong truy vấn
Hãy xem xét ý tưởng sau đây và cố gắng đưa mọi thứ vào mã. Trước khi chúng tôi làm, tôi muốn nêu ra một vài lưu ý ở đây
LƯU Ý QUAN TRỌNG:
Tất cả mọi thứ chưa được kiểm tra, vì vậy nó có thể là lỗi. Hãy chắc chắn để kiểm tra điều này cục bộ với gỡ lỗi được bật
Mã yêu cầu ít nhất PHP 5.3, bất kỳ phiên bản nào dưới 5.3 sẽ gây ra lỗi nghiêm trọng. Lưu ý, nếu vẫn đang sử dụng bất kỳ phiên bản nào dưới PHP 5.5, bạn đã nâng cấp từ lâu rồi
Sửa đổi và lạm dụng mã khi bạn thấy phù hợp với nhu cầu chính xác của bạn
Ý TƯỞNG ÁNH SÁNG:
Chúng ta sẽ cần gì
Để làm cho mọi thứ hoạt động, chúng tôi sẽ cần những điều sau đây:
Số trang hiện tại đang được xem
Các posts_per_page
tùy chọn thiết lập trong cài đặt đọc
Tập quán offset
Sửa đổi thuộc $found_posts
tính của truy vấn để sửa thuộc $max_num_pages
tính
Phân trang được WP_Query
đưa ra một vài dòng mã rất đơn giản
if ( empty($q['nopaging']) && !$this->is_singular ) {
$page = absint($q['paged']);
if ( !$page )
$page = 1;
// If 'offset' is provided, it takes precedence over 'paged'.
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) {
$q['offset'] = absint( $q['offset'] );
$pgstrt = $q['offset'] . ', ';
} else {
$pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', ';
}
$limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
}
Về cơ bản điều gì xảy ra, một khi phần bù được đặt rõ ràng, paged
tham số sẽ bị bỏ qua. Tham số đầu tiên của LIMIT
mệnh đề SQL được tính toán lại từ phần bù và sẽ là số lượng bài đăng được bỏ qua trong truy vấn SQL được tạo.
Từ câu hỏi của bạn, rõ ràng khi đặt offset
thành 0
, truy vấn bù không thành công, điều này thật lạ, vì kiểm tra sau sẽ trả về đúng
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
là một số hợp lệ và sẽ trả về đúng. Nếu điều này không có trong cài đặt của bạn, bạn nên gỡ lỗi sự cố
Để quay trở lại vấn đề trong tay, chúng tôi sẽ sử dụng cùng loại logic để tính toán và đặt phần bù của chúng tôi để có được bài 1 trên trang 2 và từ đó phân trang truy vấn. Đối với trang đầu tiên, chúng tôi sẽ không thay đổi bất cứ điều gì, vì vậy các bài đăng được cho là ở trang 1 sẽ vẫn ở trang như bình thường, chúng tôi sẽ chỉ cần "ẩn" chúng sau để chúng tôi không hiển thị chúng trên trang 1
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$current_page = $q->get( 'paged' ); // Get the current page number
// We will only need to run this from page 2 onwards
if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
// Get the amount of posts per page
$posts_per_page = get_option( 'posts_per_page' );
// Recalculate our offset
$offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0
// Set our offset
$q->set( 'offset', $offset );
}
}
});
Bạn sẽ thấy các bài đăng tương tự từ trang 1 trên trang 2. Như tôi đã nói trước đây, nếu điều này không xảy ra, thì nó sẽis_numeric( 0 )
trả về sai ( không nên ) hoặc bạn có một pre_get_posts
hành động khác cũng đang cố gắng đặt bù hoặc bạn đang sử dụng việc sử dụng các posts_*
bộ lọc mệnh đề ( cụ thể hơn là post_limits
bộ lọc ). Đây sẽ là một cái gì đó bạn sẽ cần phải tự gỡ lỗi.
Vấn đề tiếp theo là sửa lỗi phân trang, tạm dừng như tôi đã nói trước đây, bạn sẽ là một trang ngắn. Đối với điều này, chúng tôi sẽ cần thêm giá trị của get_option( 'posts_per_page' )
số lượng bài đăng được tìm thấy trong truy vấn vì chúng tôi đang bù đắp truy vấn theo số tiền đó. bằng cách này, chúng tôi đang thêm 1
vào $max_num_pages
tài sản một cách hiệu quả .
add_action( 'found_posts', function ( $found_posts, $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$found_posts = $found_posts + get_option( 'posts_per_page');
}
}, 10, 2 );
Điều này sẽ sắp xếp mọi thứ, ngoại trừ trang đầu tiên.
TẤT CẢ MỌI THỨ NGAY BÂY GIỜ ( và đặc biệt dành cho @ialocin - Tàu ngầm vàng )
Tất cả điều này nên đi vào functions.php
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$current_page = $q->get( 'paged' ); // Get the current page number
// We will only need to run this from page 2 onwards
if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
// Get the amount of posts per page
$posts_per_page = get_option( 'posts_per_page' );
// Recalculate our offset
$offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0
// Set our offset
$q->set( 'offset', $offset );
}
}
});
add_filter( 'found_posts', function ( $found_posts, $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$found_posts = $found_posts + get_option( 'posts_per_page');
}
return $found_posts;
}, 10, 2 );
LỰA CHỌN TRANG ĐẦU TIÊN
Có một vài lựa chọn ở đây:
LỰA CHỌN 1
Tôi rất có thể sẽ đi cho tùy chọn này. Những gì bạn muốn làm ở đây là tạo ra một category-news.php
( nếu bạn chưa làm điều này ). Đây sẽ là mẫu sẽ được sử dụng bất cứ khi nào news
thể loại được xem. Mẫu này sẽ rất đơn giản
Thí dụ
<?php
get_header()
if ( !is_paged() ) { // This is the first page
get_template_part( 'news', 'special' );
} else { // This is not the first page
get_template_part( 'news', 'loop' );
}
get_sidebar();
get_footer();
Như bạn có thể thấy, tôi đã bao gồm hai phần mẫu news-special.php
và news-loop.php
. Bây giờ, những điều cơ bản của hai mẫu tùy chỉnh là:
news-special.php
-> Phần mẫu này sẽ là bất cứ điều gì bạn muốn hiển thị trên trang đầu tiên. Thêm tất cả thông tin tĩnh tùy chỉnh của bạn ở đây. Hãy cẩn thận đừng gọi vòng lặp trong mẫu này vì điều này sẽ hiển thị các bài đăng của trang đầu tiên.
news-loop.php
-> Đây là mẫu mà chúng ta sẽ gọi vòng lặp. Phần này sẽ trông giống như thế này:
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
LỰA CHỌN 2
Tạo một mẫu riêng với nội dung tĩnh của bạn và chỉ cần sử dụng category_template
bộ lọc để sử dụng mẫu này khi chúng tôi xem trang đầu tiên của news
danh mục. Ngoài ra, hãy chắc chắn không gọi vòng lặp mặc định trong mẫu này. Ngoài ra, hãy đảm bảo rằng quy ước đặt tên của bạn ở đây không va chạm với tên mẫu trong cấu trúc phân cấp mẫu
Tôi hy vọng điều này là hữu ích. Hãy thoải mái nhận xét ý kiến với mối quan tâm
BIÊN TẬP
Nhờ OP, có một lỗi nhất định trong WP_Query
lớp, hãy kiểm tra vé trac # 34060 . Mã tôi đã đăng là từ Wordpress v4.4 và lỗi được sửa trong phiên bản này.
Tôi đã quay lại mã nguồn của v4.3, nơi có lỗi và tôi có thể xác nhận rằng 0
nó bị bỏ qua khi được đặt làm giá trị thành offset
mã chỉ đơn giản là kiểm tra xem offset
tham số có phải không empty
. 0
được lấy làm trống trong PHP. Tôi không chắc chắn nếu hành vi này (lỗi) chỉ được tìm thấy trong phiên bản v4.3 hoặc trong tất cả các phiên bản trước đó (theo vé, lỗi này là trong phiên bản 4.3), nhưng có một bản vá cho lỗi này mà bạn có thể kiểm tra ra trong vé trac. Như tôi đã nói, lỗi này chắc chắn đã được sửa trong v4.4
return $found_posts;
sau câu lệnh if trong hành động Found_posts. Cảm ơn!