問題描述
我正在嘗試在我的主題中建立一個類別模板,如果使用者位於存檔的第一頁,則會顯示靜態內容,然後在以下頁面上顯示類別中的帖子。我基本上是嘗試複製 Wired.com 上的類別行為,其中 http://www.wired.com/category/design 是一個著陸頁,而/category /design /page /1 顯示了類似於期望在類別歸檔中的反向按時間順序排列的列表。
這裡的關鍵是,我沒有在第一頁上顯示類別歸檔中的任何帖子,所以我需要下一頁從第一個帖子開始。如果’paged’ 查詢 var 為 2,我首先嚐試使用 offset and manual pagination 來設定查詢的偏移量為 0 。但是當設定為零時,偏移量被忽略,所以我可以做的最好是將偏移量設定為 1,並從該類別中的第二個職位。
這是我新增到 functions.php 中的:
add_action('pre_get_posts', 'category_query_offset', 1 );
function category_query_offset(&$query) {
// Before anything else, make sure this is the right query
if (!$query->is_category('news')) {
return;
}
// Next, determine how many posts per page
$ppp = get_option('posts_per_page');
//Next, detect and handle pagination
if ($query->is_paged) {
// Manually determine page query offset
$page_offset = (($query->query_vars['paged']-1) * $ppp) - $ppp;
// Apply adjust page offset
$query->set('offset', $page_offset );
}
}
什麼會更好,以及它顯示的是使用預設分頁,以便帖子從第 1 頁開始,但為靜態內容插入頁面 0 。假設’paged’ 為 1,那麼’paged’ 為 0,並顯示第一頁帖子,這樣就可以顯示靜態內容。問題是’paged’ 從不是 1,因為 WordPress 將’paged’ 設定為零,當使用者請求第一頁。這意味著’paged’ 對於/category /news /page /1 和/category /news 都是 0 。
有沒有辦法檢查使用者是否要求/category /news /page /1 而不是/category /news?沒有,是否有一種方法來顯示從第 2 頁開始的類別中的所有帖子?
最佳解決方案
這是一個非常有趣的問題 (我特別為您的方法和研究而升級了) 。這裡的大麴線球是查詢的第一頁:
-
您無法設定查詢以返回第一頁上的
0
帖子 -
透過將每頁的頁面內容向上移動一頁,您將會丟失最後一頁,因為查詢仍將只具有相同的帖子數量,因此
$max_num_pages
屬性仍然保持不變
我們將需要以某種方式”trick” WP_Query
類返回我們的帖子 corectly 與一個頁面的偏移,並且還得到正確的頁數,以便不鬆動查詢中的最後一頁
讓我們來看看下面的想法,並嘗試將所有內容都放在程式碼中。在我們做之前,我想在這裡提幾點
重要筆記:
-
一切都是未經測試的,所以它可能是錯誤的。確保在本地進行測試,並開啟除錯開關
-
該程式碼至少需要 PHP 5.3,5.3 以下版本會導致致命錯誤。請注意,如果仍然使用下面的 PHP 5.5 版本,您應該已經很久以前升級了
-
修改和濫用您認為適合您的確切需求的程式碼
光線:
我們需要什麼
為了使一切正常,我們將需要以下內容:
-
正在檢視的當前頁碼
-
posts_per_page
選項在閱讀設定中設定 -
定製
offset
-
修改查詢的
$found_posts
屬性以更正$max_num_pages
屬性
分頁是 WP_Query
下來一個非常簡單的幾行程式碼
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'];
}
基本上發生了什麼,一旦偏移被明確設定,paged
引數被忽略。 SQL LIMIT
子句的第一個引數從偏移量重新計算,並將是生成的 SQL 查詢中要跳過的帖子數。
從您的問題,顯然是將 offset
設定為 0
時,偏移查詢失敗,這是奇怪的,因為以下檢查應該返回 true
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
是一個有效的數字,應該返回 true 。如果您的安裝沒有,您應該除錯問題
為了回到手頭的問題,我們將使用相同的邏輯來計算和設定我們的偏移量,以獲得第 2 頁的帖子 1,並從中分頁查詢。對於第一頁,我們不會更改任何內容,因此假設在第 1 頁上的帖子仍然正常,我們稍後將需要”hide”,以便我們不在第 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 );
}
}
});
您應該看到第 2 頁的第 1 頁上的相同帖子。如前所述,如果沒有發生這種情況,is_numeric( 0 )
將返回 false(不應該),或者還有另一個 pre_get_posts
操作,也試圖設定一個偏移量或者您正在使用 posts_*
子句過濾器 (更具體地說是 post_limits
過濾器) 。這將是你需要自己除錯的東西。
下一個問題是糾正分頁,如前所述,你將是一個簡短的頁面。為此,我們將需要將 get_option( 'posts_per_page' )
的值新增到查詢中發現的帖子數量,因為我們將查詢量抵消該量。透過這樣做,我們有效地將 1
新增到 $max_num_pages
屬性。
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 );
這應該排序所有,除了第一頁。
現在全部 (特別為 @ialocin – Yellow Submarine)
這一切都應該進入 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 );
第一頁選項
這裡有幾個選項:
選項 1
我可能會選擇這個選項。你想要做的是建立一個 category-news.php
(如果還沒有這樣做) 。這將是每當檢視 news
類別時將使用的模板。這個模板很簡單
例
<?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();
如您所見,我已經包括兩個模板部分,news-special.php
和 news-loop.php
。現在,兩個自定義模板的基礎是:
-
news-special.php
– > 這個模板部分將是您想要顯示在第一頁上的任何內容。在這裡新增所有您的自定義靜態資訊。要小心,不要在此模板中呼叫迴圈,因為這將顯示第一頁的帖子。 -
news-loop.php
– > 這是我們呼叫迴圈的模板。本節將如下所示:global $wp_query; while ( have_posts() ) { the_post(); // Your template tags and markup }
選項 2
使用靜態內容建立一個單獨的模板,當我們檢視 news
類別的第一頁時,只需使用 category_template
篩選器即可使用此模板。另外,請確保不要呼叫此模板中的預設迴圈。另外,請確保這裡的命名約定不會與模板層次結構中的模板名稱相沖突
我希望這是有用的。隨心所欲地發表評論
EDIT
感謝 OP,WP_Query
類有一個明確的錯誤,檢查 trac ticket #34060 。我釋出的程式碼來自 Wordpress v4.4,該版本中修復了錯誤。
我回到 v4.3 的原始碼,那裡的 bug 是,當我設定為 offset
的值時,我可以確認 0
被忽略,因為程式碼只是檢查 offset
引數是 empty
。 PHP 中的 0
為空。我不知道這個行為 (錯誤) 是否僅在 v4.3 或所有以前的版本中發現 (根據機票,該錯誤在 v4.3 中),但是有一個補丁可以檢查這個錯誤在 trac 門票裡。就像我說的,這個 bug 在 v4.4 中一定是固定的
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。