【WordPress】特定のカテゴリーの投稿を表示する方法|WP_Query・スラッグ指定・ページネーション

WordPressで「特定のカテゴリーの投稿だけを一覧表示したい」というとき、WP_Query でカテゴリーを指定して取得します。ポイントはカテゴリーの指定方法(IDよりスラッグが安全)と、件数・ページネーションの扱いです。

この記事でわかること

  • スラッグ指定category_name)でカテゴリーの投稿を取得(推奨)
  • 名前・スラッグからカテゴリーIDを取得する
  • posts_per_page => -1 の注意とページネーション
  • アーカイブページ自体を変えるなら pre_get_posts
スポンサーリンク

スラッグでカテゴリーの投稿を取得する(推奨)

カテゴリーの指定は、IDより「スラッグ」(category_name)が安全です。IDはサイトを移行すると変わることがありますが、スラッグは固定できるためです。

WP_Query:newsカテゴリーの投稿を表示
$args = array(
  'category_name'  => 'news', // カテゴリーのスラッグ
  'posts_per_page' => 5,      // 表示件数(後述の理由で件数は指定推奨)
);

$query = new WP_Query($args);

if ($query->have_posts()) :
  while ($query->have_posts()) : $query->the_post();
    the_title('<h3>', '</h3>'); // echoは不要(the_title自体が出力)
    the_excerpt();
  endwhile;
  wp_reset_postdata(); // サブループの後は必ずリセット
else :
  echo '<p>このカテゴリーには投稿がありません。</p>';
endif;

カテゴリーIDを取得する(cat で指定したい場合)

ID(cat)で指定したい場合は、名前やスラッグからIDを取得できます。管理画面でカテゴリーを編集する際のURL (…?taxonomy=category&tag_ID=5…)の tag_ID でも確認できますが、コードで動的に取得するとハードコードを避けられます。

カテゴリー名・スラッグからIDを取得
// カテゴリー名から
$cat_id = get_cat_ID('ニュース');

// スラッグから(存在しない場合に備えてチェック)
$term = get_category_by_slug('news');
$cat_id = $term ? $term->term_id : 0;

// 取得したIDで指定
$args = array('cat' => $cat_id, 'posts_per_page' => 5);

カテゴリーの取得方法全般(配列で取得・階層など)は記事のカテゴリーを取得する方法(完全ガイド)にまとめています。

「全件表示(-1)」の注意とページネーション

posts_per_page => -1 は安易に使わない
-1該当カテゴリーの全投稿を一度に取得します。投稿数が多いサイトではメモリ不足やタイムアウトの原因になり、表示も重くなります。基本は件数を指定し、続きはページネーションで見せましょう。

カスタムクエリでページ送りを付けるには、paged を渡し、paginate_links() にそのクエリの総ページ数を渡します。

WP_Query:ページネーション付き
$paged = max(1, get_query_var('paged'));

$query = new WP_Query(array(
  'category_name'  => 'news',
  'posts_per_page' => 10,
  'paged'          => $paged,
));

// (ここでループ)

echo paginate_links(array(
  'total'   => $query->max_num_pages, // このクエリの総ページ数
  'current' => $paged,
));
wp_reset_postdata();

ページネーションの詳細(404対策・固定ページでの注意)はプラグインなしでページネーションを実装する方法を参照してください。

カテゴリーアーカイブ自体を変えるなら pre_get_posts

上のコードは別に作るサブループです。「カテゴリーアーカイブページ(/category/news/)そのものの表示件数や条件を変えたい」場合は、テンプレートで new WP_Query() を作るのではなく、pre_get_postsメインクエリを変更します(ページネーションも正しく動きます)。

functions.php:newsアーカイブの表示件数を変更
add_action('pre_get_posts', function ($query) {
  if (is_admin() || !$query->is_main_query()) {
    return;
  }
  if ($query->is_category('news')) {
    $query->set('posts_per_page', 12);
  }
});

複数カテゴリーやタクソノミーをまたいだ絞り込みは複数のタクソノミー・タームで記事を絞り込む方法、AND・OR・NOTを組み合わせた複雑な条件はWP_Queryで複雑な条件検索を実装する方法を参照してください。

よくある質問(FAQ)

Qショートコードでカテゴリーの投稿を表示するには?
AWP_Query をショートコードにまとめると、記事本文や固定ページから呼べます。add_shortcode('cat_posts', function ($atts) { $a = shortcode_atts(array('cat' => '', 'count' => 5), $atts); $q = new WP_Query(array('category_name' => $a['cat'], 'posts_per_page' => (int) $a['count'])); /* ループしてreturn */ }); のように書きます(出力は必ずreturnします)。
QIDとスラッグ、どちらで指定すべきですか?
Aスラッグ(category_name)が安全です。IDはサイト移行やDB操作で変わることがありますが、スラッグは固定できます。どうしてもIDが必要な場合は get_category_by_slug('news')->term_id のようにコードで取得してハードコードを避けましょう。
Q現在の記事と同じカテゴリーの関連記事を出すには?
Aget_posts(array('category__in' => wp_get_post_categories(get_the_ID()), 'post__not_in' => array(get_the_ID()), 'numberposts' => 5)) で、現在の記事を除いた同カテゴリーの記事を取得できます。

まとめ

  • 指定category_name(スラッグ)が安全。IDは get_cat_ID / get_category_by_slug で取得
  • 件数-1(全件)は重い。件数指定+ページネーション
  • 後片付け:サブループの後は wp_reset_postdata()
  • アーカイブ自体を変えるなら pre_get_postsnew WP_Query ではない)

スラッグ指定と件数管理を押さえれば、環境が変わっても壊れないカテゴリー別一覧が作れます。