これは非常に興味深い質問です(私は特にあなたのアプローチと研究のために賛成しています)。ここでの大きな曲線は、クエリの最初のページです。
WP_Query
1ページのオフセットを使用して投稿を正しく返すようにクラスを「だます」必要があります。また、クエリの最後のページが失われないように、正しいページ数を取得する必要があります。
次のアイデアを見て、すべてをコードに入れてみましょう。ただしその前に、ここでいくつか注意点を挙げておきます。
重要な注意:
電球のアイデア:
何が必要か
すべてを機能させるには、次のものが必要です。
改ページは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にあると想定される投稿は通常どおりページ上にあります。ページに表示しないように、後で「非表示」にするだけで済みます。 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 );
これにより、最初のページを除くすべてがソートされます。
これはすべて入ります 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();
あなたが見ることができるように、私は2つのテンプレートパーツを含め、しているnews-special.php
とnews-loop.php
。2つのカスタムテンプレートの基本は次のとおりです。
news-special.php
->このテンプレートパーツは、最初のページに表示したいものです。ここにすべてのカスタム静的情報を追加します。最初のページの投稿が表示されるため、このテンプレートでループを呼び出さないように注意してください。
news-loop.php
->これは、ループを呼び出すテンプレートです。このセクションは次のようになります。
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
オプション2
静的コンテンツを含む別のテンプレートを作成し、category_template
フィルターを使用して、news
カテゴリーの最初のページを表示するときにこのテンプレートを使用します。また、このテンプレートではデフォルトのループを呼び出さないでください。また、ここでの命名規則がテンプレート階層内のテンプレート名と衝突しないことを確認してください
これがお役に立てば幸いです。気になるコメントはお気軽にどうぞ
編集
OPのおかげで、WP_Query
クラスに明確なバグがあります。tracチケット#34060を確認してください。私が投稿したコードはWordpress v4.4からのもので、このバージョンではバグが修正されています。
バグがあるv4.3のソースコードに戻りました。コードがパラメーターがであるかどうかを確認するだけなので、0
値としてに設定すると無視されることを確認できます。PHPでは空と見なされます。この動作(バグ)がv4.3のみで見つかるか、以前のすべてのバージョンで見つかるかはわかりませんが(チケットによれば、このバグはv4.3にあります)、このバグのパッチを確認できます。トラックチケットで出ます。私が言ったように、このバグは間違いなくv4.4で修正されていますoffset
offset
empty
0
return $found_posts;
、found_postsアクションのifステートメントの後だけです。ありがとう!