pre_get_posts でアーカイブ(一覧)ページの表示を工夫する

WordPress のロゴ

標準的な WordPpress とテーマのセットでは、アーカイブページなどに用いられる have_posts() 関数は、投稿ページを規定のページ数だけ取得するために利用されます。 しかしながら、例えば"特定のページを表示したくない場合" や、"投稿ページと固定ページの両方の新着が欲しい" 場合には、カスタマイズが必要です。 ここでは pre_get_posts アクションをフックして、アーカイブ(一覧)ページの表示方法を工夫します。

pre_get_posts アクションとは

pre_get_posts アクションを簡単に説明すると、post (投稿) を取得する前に実行されるアクションです。 したがって、投稿を取得するよりも前に、取得する条件などを調整(変更)すれば、実際に取得するタイミングで条件に見合った結果が得られる、ということです。 ここで調整するパラメータは クエリ (query) です。

クエリ(query)とは

クエリを簡単に説明すると、データベースやサーバに問い合わせるときのパラメータです。 最も身近に見られる例は URL です。例えば WordPress で表示されるアドレスの末尾の方に &= が見つかります。 それがクエリの正体です。あるアドレス A に対し、B と C というパラメータを与えてページを表示したい、というときは、A?B=value&C=value となります。 詳細を理解していなくても pre_get_posts アクションを利用することは可能です。

functions.php への追記

pre_get_posts アクションフックを利用して処理を実行するために、例えば次のようなコードを functions.php に追記します。 このコードはトップページ(home, index.php または home.php など)の表示の際に、pre_get_posts にフックして、そのクエリを調整します。

function my_pre_get_posts( $query )
{
    if( is_admin() || ! $query->is_main_query() )
    {
        return;
    }

    if ( $query->is_home() )
    {
        $query->set( 'posts_per_page', '5' );
        $query->set( 'post_type', array('post', 'page') ); 
       //to exclude undefined category.
        $query->set( 'category_not_in', '1');
        $query->set( 'cat', '-1' );//same as category_not_in
    }
}
add_action( 'pre_get_posts', 'my_pre_get_posts' );

先にこのコードについて簡単に説明します。このコードは次のような処理を実行します。

クエリ、つまりページを一覧して欲しいという命令が、is_home(トップページに対するもの)だった場合、 カテゴリID が 1 (一般的には"未分類")の記事を除く、投稿(post) あるいは 固定ページ(page) を最大 5ページ取得する。

したがってこのコードはカテゴリ別アーカイブやタグ別アーカイブには効果がない、ということです。 また、WordPress の "表示設定" などで、最大表示数が 10 と設定されている場合などであっても、 トップページには 最大 5 件の記事しか表示されない、ということでもあります。

作り自体はシンプルなのでコード自体を読んでしまえば大よそどのようなことができるか理解できますが、以降にもう少しだけ詳細な解説を続けます。