web-dev-qa-db-ja.com

最初のページと残りのページ番号付きページの別の 'posts_per_page'設定?

最初のページ付けされたページ(ホーム、アーカイブ、検索など)とそれ以外のページに異なる数の投稿が表示されるようにposts_per_pageクエリ設定をどのように設定しますか?

たとえば、カテゴリアーカイブのページ付けされたページの最初のページに10件、残りのページに15件の投稿を表示するとします。どうすればいいのですか?

これは動作します

function itsme_category_offset( $query ) {
  if( $query->is_category() && $query->is_main_query() ) {

    if( !$query->is_paged() ) {

      $query->set( 'posts_per_page', 10 );

    } else {

      $query->set( 'offset', 10 );
      $query->set( 'posts_per_page', 15 );

    }
  }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

しかし... ...

WP_Query()のページ付けパラメータのCodexエントリ によれば:

offset(int) - 移動または通過するポストの数 警告:offsetパラメータを設定すると、ページングされたパラメータが上書きされて無視され、ページ区切りが中断されます

そして 回避策のためのリンクされたCodexエントリ :に従って:

オフセットはWordPressで内部的にページ区切りを計算して処理するために使用されるため、クエリでハードコーディングされたオフセットを指定するとページ区切りが壊れる可能性があります。

示された回避策はfound_postsフィルタにフックしてオフセットを確立する関数を使用します。私はこのようなことをすべきだと思います:

function itsme_category_offset( $query ) {
  if( $query->is_category() && $query->is_main_query() ) {
    $paged = get_query_var( 'paged' );

    if( 0 == $paged ) {

      $query->set( 'posts_per_page', 10 );

    } else {

      $offset = 10 + ( ($paged - 2) * 15 );
      $query->set( 'offset', $offset );
      $query->set( 'posts_per_page', 15 );

    }
  }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
  $paged = get_query_var( 'paged' );
  if( $query->is_category() && $query->is_main_query() ) {
    if( 0 == $paged ) {

      $offset = 0;

    } else {

      $offset = 10 + ( ($paged - 2) * 15 );

    }

    return $found_posts - $offset;
  }
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination' );

私の単純な関数はすでに機能しているので、Codexの警告はまだ正しいですか? (つまり、2番目のコードブロックに示すようにそれを実行する必要がありますか?)このオフセット/ページ付けの問題は、最近のバージョンのWordPressで修正されましたか?そしてもしそうなら:どのように?

6
its_me

ケース1:単純オフセット

カテゴリアーカイブの投稿を 'n'だけ 'オフセット'したい、つまり単にアーカイブ内の最初/最新の 'n'個の投稿を表示したくない場合。

つまり、(WPダッシュボード>設定>閲覧posts_per_page設定が10に設定されていることを考慮すると、投稿11から20までを最初のページに表示します(例:example.com/category/tech/)。 2番目の21から30(例:example.com/category/tech/page/2/)、3番目の31から40など。

とにかく、これがあなたのやり方です。

/*
 * Offset posts by 10 on 'Techonology (tech)' category archive
 */
function itsme_category_offset( $query ) {
    $offset = 10;
    $ppp = get_option( 'posts_per_page' );
    $paged = $query->query_vars[ 'paged' ];

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        if( !is_paged() ) {

            $query->set( 'offset', $offset );

        } else {

            $paged_offset = $offset + ( ($paged - 1) * $ppp );
            $query->set( 'offset', $paged_offset );

        }
    }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

それから、もう1つあります。ページネーションを作成する前に、WordPressはWP_Queryクラスがクエリ実行時に発見したと報告した投稿の総数を調べます。

そのため、ページ付けを正しく機能させるには、クエリで見つかった投稿の総数からoffsetを削除する必要があります(最初の10件の投稿は表示されていないため)。そして、これはあなたがそうする方法です:

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
    $offset = 10;

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        return( $found_posts - $offset );
    }
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination', 10, 2 );

それでおしまい!

PS: (より技術的な説明は here に​​あります。)


ケース2:条件付きオフセット

私の場合と同じように、アーカイブの最初のページに 'm'個の投稿を表示し、他のページに 'n'個の投稿を表示します。

つまり、(アーカイブの最初のページに5つの投稿のみを表示し、残りのページはWP Dashboard>設定>閲覧posts_per_page設定に従うようにします。 _は10に設定されています。最初のページに1から5までの投稿(例:example.com/category/tech/)、2番目のページに6から15(例:example.com/category/tech/page/2/)、3番目のページに16から25という具合です。

あなたがそうする方法は次のとおりです。

/*
 * Show a different no. of posts on the first page, and the rest
 * of the pages of 'Techonology (tech)' category archive
 */
function itsme_category_offset( $query ) {
    $ppp = get_option( 'posts_per_page' );
    $first_page_ppp = 5;
    $paged = $query->query_vars[ 'paged' ];

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        if( !is_paged() ) {

            $query->set( 'posts_per_page', $first_page_ppp );

        } else {

            // Not going to explain the simple math involved here
            $paged_offset = $first_page_ppp + ( ($paged - 2) * $ppp );
            $query->set( 'offset', $paged_offset );

            /*
             * As we are not adding a custom `$query->set( 'posts_per_page', ... );`,
             * the default `posts_per_page` setting from WP Dashboard > Settings > Reading
             * will be applied here.
             */

        }
    }
}
add_action( 'pre_get_posts', 'itsme_category_offset' );

この場合は複雑です。そのため、最初にfound_posts関数がどのように見えるべきかを見てみましょう。

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
    $ppp = get_option( 'posts_per_page' );
    $first_page_ppp = 5;

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        if( !is_paged() ) {

            return( $found_posts );

        } else {

            return( $found_posts - ($first_page_ppp - $ppp) );

        }
    }
    return $found_posts;
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination', 10, 2 );

In とは異なり、ケース#1 とは異なり、ここでは合計から投稿を削除していません。それらすべてを表示する必要があります。セット番号を見せたい以外は。カテゴリアーカイブの最初のページに投稿数が増えています。残りのページ番号付きページの投稿数。

問題は、数を計算するためです。ページネーションを生成するためのページ数で、$query(WP_Query)は現在のページのposts_per_page設定を調べます。最初のページを除く他のすべてのページでは「10」に設定されているため、最初のページを除く他のページでは、$queryはすべてのページで同じであると見なし、最初のページも含めてページネーションの計算を開始します。それに基づいて。

そのため、例えば2ページ目(合計投稿数を「20」とした場合)によると、

  • $queryページ付けは10 + 10でなければなりません
  • しかし、 正しい ページ付けは、5 + 10 + 5になります(最初のpre_get_posts関数では、最初のページのページ付けを '5'に設定しているため)。

したがって、2ページ目(または1ページ目以外のページ)にある場合は、この例のように、$queryに合計数を超えないようにする必要があります。投稿数が25であるため、このような正しいページ区切りが生成されます。

5 1ページ目の投稿数+ 10 2ページ目の投稿数+ 5 3ページ目の投稿数

...実際にこれをやっていると思います。

10 1ページ目の投稿数+ 10 2ページ目の投稿数+ 5 3ページ目の投稿数

また、found_postsフィルタは特定のページに実際に表示される投稿数にはまったく影響しないため、最初の関数のposts_per_page設定が優先され、ページ付けの問題はありません。

それは物事を片付けるはずです。 (そして、何かがうまくいっていないか教えてください)


そのため、質問に直接答えるには、はい、found_postsフィルタフックにフックする関数を使用してカスタムルールに従って$queryを調整し、改ページがめちゃくちゃにならないようにする必要があります。

9
its_me

上記についてコメントするのに十分なスタック交換ポイントがありませんが、訂正があります。

ケース1:単純オフセットは私のサイトでは非常にうまく機能しました。特別な条件が満たされないときにデフォルトのオフセットを返すように修正が必要です。

function itsme_adjust_category_offset_pagination( $found_posts, $query ) {
    $offset = 10;

    if( $query->is_category( 'tech' ) && $query->is_main_query() ) {
        return( $found_posts - $offset );
    } else {
        return $found_posts;
    }
}
add_filter( 'found_posts', 'itsme_adjust_category_offset_pagination', 10, 2 );
1
Oxfordian3