技術ブログ
【WordPress】カテゴリごとに最新5件を並べ、「もっと見る」で続きを読み込む ── ブログのトップ・カテゴリページを作ってみた
「ブログのトップにカテゴリごとの最新記事を5件ずつ並べ、もっと見るを押したら続きをその場で読み込みたい」──WordPress の標準のテンプレートには、この形の一覧はありません。
本記事では、この一覧をテーマに部品を4つ足すだけで作り、WordPress 7.1.4 の検証環境(クラシックテーマ)で動かしました。押し切ったときに抜けや重複が出ないかを、正解の並びと1件ずつ突き合わせて確かめています。
① 最初の5件は PHP(WP_Query)で出す。カテゴリを
cat で指定すると子カテゴリの記事も含まれる(→ 4章)② 続きは REST API の独自の窓口から、同じテンプレートで作った HTML を受け取って足す(→ 4章・5章)
③ もっと見るはふつうのリンクにしておく。JavaScript が動かなくてもカテゴリページへ移れる(→ 5章)
1. 結論
| ご要望 | 答え |
|---|---|
| ブログのトップにカテゴリ一覧、カテゴリページに子カテゴリ一覧を出したい | できます。get_categories() の parent に、トップでは 0(親カテゴリ)、カテゴリページでは今のカテゴリの ID(その子カテゴリ)を渡します。同じ関数1つで両方に使えます。 |
| カテゴリごとに最新5件を出したい | できます。カテゴリごとに WP_Query で5件取ります。cat で指定すると、親カテゴリの欄には子カテゴリの記事も入ります。 |
| もっと見るで追加表示したい(非同期) | できます。REST API に「カテゴリ ID と何件目から」を渡すと、続きの5件の HTML を返す窓口を作り、JavaScript で一覧の末尾に足します。押し切ったときの並びが、正解(日付の新しい順の全件)と1件も違わないことを確かめました。 |

2. 仕組みとファイルの構成
[ページを開いたとき] PHP で、カテゴリごとに最新5件を出す
│ 5件より多いカテゴリだけ「もっと見る」を付ける(中身はカテゴリページへのリンク)
▼
[もっと見るを押す] JavaScript がリンクの移動を止め、API に問い合わせる
│ GET /wp-json/bit/v1/category-posts?cat=3&offset=5
▼
[サーバ] 同じ条件で6件目から5件取り、最初の5件と同じテンプレートで HTML にして返す
│ { "html": "<li>…", "next_offset": 10, "has_more": true }
▼
[画面] 一覧の末尾に足す。もう無ければボタンを消す
| ファイル | 役割 |
|---|---|
template-parts/content/post-item.php |
記事1件分の HTML。最初の5件と、あとから足す分の両方で使う |
inc/jnm-function-category-sections.php |
一覧を出す関数 bit_category_sections() と、続きを返す API |
js/category-more.js |
もっと見るを押したときの処理 |
css/category-sections.css |
見た目の見本 |
home.php・category.php・functions.php |
呼び出しを足す(6章) |
3. 記事1件分のテンプレート
日付・子カテゴリ名・タイトル(35文字で切る)を出します。WordPress はタイトルの & や引用符を & のような書き方に置き換えて返すので、ふつうの文字に戻してから35文字で切ります(そのまま切ると、書き方の途中で切れて「Q&A “まとめ” と ‘…」のように化けました)。最初の5件も、あとから足す5件も、このファイル1つで作るのがポイントです。JavaScript 側で HTML を組み立てないので、見た目を変えるときに直す場所が1か所で済みます。
<?php
/**
* 記事1件分(カテゴリ別一覧の最初の5件と、MORE で足す分の両方で使う)
* category.php の「ここから記事」と同じ見た目
*/
?>
<li class="catSection__item">
<dl>
<dd class="date"><?php echo esc_html( get_post_time( 'Y.m.d' ) ); ?></dd>
<?php foreach ( get_the_category() as $cat ) : ?>
<?php if ( $cat->parent ) : ?>
<span class="category"><?php echo esc_html( $cat->name ); ?></span>
<?php endif; ?>
<?php endforeach; ?>
<dt>
<a href="<?php the_permalink(); ?>">
<?php
// get_the_title() は & や引用符を & “ などに置き換えて返すので、ふつうの文字に戻してから切る
$title = html_entity_decode( get_the_title(), ENT_QUOTES | ENT_HTML5, 'UTF-8' );
echo esc_html( mb_strlen( $title, 'UTF-8' ) > 35 ? mb_substr( $title, 0, 35, 'UTF-8' ) . '…' : $title );
?>
</a>
</dt>
</dl>
</li>
4. 一覧を出す関数と、続きを返す API
<?php
/**
* カテゴリごとに最新5件を並べ、「もっと見る」で5件ずつ追加する(非同期)
*
* 使い方:
* ブログのトップ(home.php) … bit_category_sections( 0 ); → 親カテゴリごと
* カテゴリページ(category.php)… bit_category_sections( get_queried_object_id() ); → 子カテゴリごと
*/
define( 'BIT_CAT_PER_PAGE', 5 );
/**
* 1カテゴリ分の記事を取る(子カテゴリの記事も含む)
*/
function bit_category_posts_query( $cat_id, $offset ) {
return new WP_Query( array(
'post_type' => 'post',
'post_status' => 'publish',
'cat' => $cat_id, // 子カテゴリの記事も含む
'posts_per_page' => BIT_CAT_PER_PAGE,
'offset' => $offset,
'orderby' => 'date',
'order' => 'DESC',
'ignore_sticky_posts' => true,
) );
}
/**
* 記事の <li> を並べた HTML を返す
*/
function bit_category_posts_html( WP_Query $q ) {
ob_start();
while ( $q->have_posts() ) {
$q->the_post();
get_template_part( 'template-parts/content/post-item' );
}
wp_reset_postdata();
return ob_get_clean();
}
/**
* カテゴリの一覧と、カテゴリごとの最新5件を出す
* 出したら true、出す欄が無ければ false を返す
*/
function bit_category_sections( $parent_id = 0 ) {
$cats = get_categories( array(
'parent' => $parent_id,
'hide_empty' => false,
'exclude' => array( get_option( 'default_category' ) ), // 未分類は出さない
) );
// 先に各カテゴリの最新5件を取り、公開記事があるカテゴリだけを残す(一覧と欄をそろえる)
$sections = array();
foreach ( $cats as $cat ) {
$q = bit_category_posts_query( $cat->term_id, 0 );
if ( $q->have_posts() ) {
$sections[] = array( $cat, $q );
}
}
if ( ! $sections ) {
return false;
}
wp_enqueue_script( 'bit-category-more' );
wp_enqueue_style( 'bit-category-sections' );
// カテゴリ一覧(ページ内リンク)
echo '<nav class="catNav"><ul>';
foreach ( $sections as list( $cat ) ) {
// 飛び先はカテゴリの番号で作る(日本語名のカテゴリはスラッグが %e6… になり、テーマのスクロール処理が読めない)
printf( '<li><a href="#cat-%d">%s</a></li>', (int) $cat->term_id, esc_html( $cat->name ) );
}
echo '</ul></nav>';
foreach ( $sections as list( $cat, $q ) ) {
$children = get_categories( array( 'parent' => $cat->term_id ) );
?>
<section class="catSection" id="cat-<?php echo (int) $cat->term_id; ?>">
<h3 class="catSection__title"><a href="<?php echo esc_url( get_category_link( $cat ) ); ?>"><?php echo esc_html( $cat->name ); ?></a></h3>
<?php if ( $children ) : ?>
<ul class="catSection__children">
<?php foreach ( $children as $child ) : ?>
<li><a href="<?php echo esc_url( get_category_link( $child ) ); ?>"><?php echo esc_html( $child->name ); ?></a></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<ul class="catSection__list" aria-live="polite">
<?php echo bit_category_posts_html( $q ); // phpcs:ignore -- post-item.php で個別にエスケープ済み ?>
</ul>
<?php if ( $q->found_posts > BIT_CAT_PER_PAGE ) : ?>
<?php // JavaScript が動かないときはカテゴリページへのふつうのリンクとして働く ?>
<a class="catSection__more" href="<?php echo esc_url( get_category_link( $cat ) ); ?>"
data-cat="<?php echo (int) $cat->term_id; ?>" data-offset="<?php echo (int) BIT_CAT_PER_PAGE; ?>">もっと見る</a>
<?php endif; ?>
</section>
<?php
}
return true;
}
/**
* 追加分を返す API: GET /wp-json/bit/v1/category-posts?cat=3&offset=5
*/
add_action( 'rest_api_init', function () {
register_rest_route( 'bit/v1', '/category-posts', array(
'methods' => 'GET',
'permission_callback' => '__return_true', // 公開記事だけを返すので誰でも可
'args' => array(
'cat' => array( 'required' => true, 'type' => 'integer', 'minimum' => 1 ),
'offset' => array( 'required' => true, 'type' => 'integer', 'minimum' => 0, 'maximum' => 10000 ),
),
'callback' => function ( WP_REST_Request $req ) {
$cat = get_category( (int) $req['cat'] );
if ( ! $cat || is_wp_error( $cat ) ) {
return new WP_Error( 'bit_no_category', 'カテゴリがありません。', array( 'status' => 404 ) );
}
$offset = (int) $req['offset'];
$q = bit_category_posts_query( $cat->term_id, $offset );
$next = $offset + $q->post_count;
return array(
'html' => bit_category_posts_html( $q ),
'next_offset' => $next,
'has_more' => $next < $q->found_posts,
);
},
) );
} );
add_action( 'wp_enqueue_scripts', function () {
wp_register_script(
'bit-category-more',
get_stylesheet_directory_uri() . '/js/category-more.js',
array(),
'1.1.0',
array( 'in_footer' => true, 'strategy' => 'defer' )
);
wp_register_style( 'bit-category-sections', get_stylesheet_directory_uri() . '/css/category-sections.css', array(), '1.0.0' );
if ( is_home() || is_category() ) {
wp_enqueue_style( 'bit-category-sections' ); // <head> で読む(画面のちらつきを防ぐ)
}
wp_localize_script( 'bit-category-more', 'bitCategoryMore', array(
'endpoint' => esc_url_raw( rest_url( 'bit/v1/category-posts' ) ),
) );
} );
4-1. 子カテゴリの記事も含める
WP_Query の cat にカテゴリ ID を渡すと、子カテゴリの記事も含めて取れます。親カテゴリ「お知らせ」に記事を直接付けていなくても、子の「イベント」「メディア掲載」の記事が新しい順に並びます。親カテゴリの記事だけにしたいときは、cat の代わりに category__in を使います。
4-2. 公開記事のあるカテゴリだけを出す
先に各カテゴリの最新5件を取り、公開記事が1件以上あるカテゴリだけで、上のカテゴリ一覧と欄の両方を作ります。こうしないと、記事の無いカテゴリ(下書きしか無いカテゴリを含む)が一覧にだけ出て、押しても行き先がありません。
4-3. カテゴリ一覧の飛び先はカテゴリの番号で作る
上のカテゴリ一覧(ページ内リンク)の飛び先は、cat-3 のようにカテゴリの番号で作ります。カテゴリ名を日本語にするとスラッグが %e6%97%a5… のような文字列になり、それを飛び先の名前に使うと、bit-template のテーマのスクロール処理(jQuery)がエラーになって画面が動きませんでした(実測)。
4-4. 「もっと見る」を出すかどうか
$q->found_posts(条件に合う全件数)が5件を超えるときだけボタンを出します。API も「次は何件目から(next_offset)」と「まだあるか(has_more)」を返すので、最後まで読み込んだらボタンが消えます。
4-5. API の入口で値を確かめる
register_rest_route() の args に型と範囲を書いておくと、WordPress が受け取る前に確かめてくれます。今回の実測では、文字・負の数・大きすぎる値・offset の付け忘れはすべて 400、ないカテゴリは 404 になりました。取るのは公開済みの記事だけ(post_status を publish に固定)なので、誰でも呼べる窓口にしても下書きや非公開の記事は漏れません(管理者でログインした状態でも混ざらないことを確かめました)。
5. 「もっと見る」の JavaScript
/*
* カテゴリ別一覧の「もっと見る」: 5件ずつ取ってきて一覧の末尾に足す
* ボタンはふつうのリンク(カテゴリページ行き)。JavaScript が動けば、ページを移らずに追加する。
*/
document.addEventListener('click', function (e) {
var btn = e.target.closest('.catSection__more');
if (!btn) return;
e.preventDefault();
if (btn.getAttribute('aria-busy') === 'true') return; // 連打で同じ記事が二重に入らないように
var list = btn.closest('.catSection').querySelector('.catSection__list');
var url = new URL(window.bitCategoryMore.endpoint, location.href);
url.searchParams.set('cat', btn.dataset.cat);
url.searchParams.set('offset', btn.dataset.offset);
btn.setAttribute('aria-busy', 'true');
btn.textContent = '読み込み中…';
fetch(url, { headers: { Accept: 'application/json' } })
.then(function (res) {
if (!res.ok) throw new Error(res.status);
return res.json();
})
.then(function (data) {
list.insertAdjacentHTML('beforeend', data.html); // サーバ側(post-item.php)でエスケープ済みの HTML
btn.dataset.offset = data.next_offset;
if (data.has_more) {
btn.textContent = 'もっと見る';
btn.removeAttribute('aria-busy');
} else {
btn.remove(); // もう無い
}
})
.catch(function () {
// 読み込めなかったら(API が止められている環境など)、リンク本来の行き先=カテゴリページへ移る
btn.textContent = 'カテゴリのページへ移ります…';
location.href = btn.href;
});
});
もっと見るは
<a href="カテゴリページ"> で出しています。JavaScript が動けばリンクの移動を止めてその場で読み込み、動かなければカテゴリページに移って続きを読めます。検索エンジンもこのリンクをたどれます。
REST API を止めるセキュリティプラグインを入れている場合などは、続きを読み込めません。そのときはリンク本来の行き先(カテゴリページ)へ移るので、閲覧者は続きを読めます(API にわざと失敗を返させて確かめました)。その場で読み込ませたいときは、プラグインの設定で
bit(この記事の API の名前空間)を例外に足してください。ログイン中の人には REST API を許す設定のプラグインもあり、その場合は作った本人には動いて見えて、閲覧者だけ失敗するので、ログアウトした状態でも試してください。
読み込み中はボタンに
aria-busy="true" を付け、その間のクリックは無視します。ダブルクリックで試しても、同じ記事が2回入らないことを確かめました。
6. テンプレートへの組み込みと CSS
トップでは 0(親カテゴリごと)、カテゴリページでは今のカテゴリの ID(子カテゴリごと)を渡します。子カテゴリが無いカテゴリページでは何も出さず、いつもの一覧だけが出ます。
カテゴリページでは、子カテゴリごとの欄の下に、もとからある「いつもの一覧」も出ます。上の欄に出た記事が下の一覧にも出るので、欄を出したときは下の一覧に「すべての記事」という見出しを付け、欄は1ページ目だけに出しています(2ページ目以降は、いつもの一覧だけ)。下の一覧を消さないのは、親カテゴリに直接付けた記事(子カテゴリに属さない記事)がそこにしか出ないためです。
--- a/home.php
+++ b/home.php
@@ -28,6 +28,7 @@
<div class="innerBasic">
<h3>MainContents</h3>
<section class="contSubBox">
+ <?php bit_category_sections( 0 ); // 親カテゴリごとに最新5件+もっと見る ?>
</section>
</div>
</section>
--- a/category.php
+++ b/category.php
@@ -29,6 +29,13 @@
<h3><?php echo esc_html($obj_cat->name); ?></h3>
<?php } ?>
+ <?php
+ // 子カテゴリごとに最新5件+もっと見る(1ページ目だけ。子が無ければ何も出さない)
+ // 欄を出したときは、下のふつうの一覧に「すべての記事」と見出しを付ける(親カテゴリに直接付けた記事もここに出る)
+ if ( ! is_paged() && bit_category_sections( $obj_cat->term_id ) ) : ?>
+ <h3 class="catAll__title">すべての記事</h3>
+ <?php endif; ?>
+
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
--- a/functions.php
+++ b/functions.php
@@ -94,6 +94,11 @@
include get_stylesheet_directory() . '/inc/jnm-settings-othres.php';
}
+/* jnm-function-category-sectionsはカテゴリごとの最新5件+もっと見る(非同期) */
+if (file_exists(get_stylesheet_directory() . '/inc/jnm-function-category-sections.php')) {
+ include get_stylesheet_directory() . '/inc/jnm-function-category-sections.php';
+}
+
/* 管理画面でGoogleMapで使用する座標取得を行わせるための設定 */
// if (file_exists(get_stylesheet_directory() . '/inc/jnm-settings-admin-googlemap.php')) {
// include get_stylesheet_directory() . '/inc/jnm-settings-admin-googlemap.php';
見た目の見本です。サイトのデザインに合わせて変えてください。
/* カテゴリ別一覧+もっと見る(見本。サイトの見た目に合わせて変える) */
.catNav ul { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 32px; padding: 0; list-style: none; }
.catNav a { display: block; padding: 6px 16px; border: 1px solid #1a365d; border-radius: 999px; color: #1a365d; text-decoration: none; }
.catNav a:hover { background: #1a365d; color: #fff; }
.catSection { margin: 0 0 48px; }
.catSection__title { margin: 0 0 8px; padding-bottom: 8px; border-bottom: 2px solid #1a365d; font-size: 1.3em; }
.catSection__title a { color: inherit; text-decoration: none; }
.catSection__children { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 0 0 12px; padding: 0; list-style: none; font-size: .9em; }
.catSection__children a::before { content: "› "; }
.catSection__list { margin: 0; padding: 0; list-style: none; }
.catSection__item dl { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 0; padding: 12px 0; border-bottom: 1px solid #e2e8f0; }
.catSection__item .date { margin: 0; color: #666; font-size: .9em; }
.catSection__item .category { padding: 0 8px; border-radius: 3px; background: #ebf4ff; color: #2a4365; font-size: .8em; }
.catSection__item dt { flex-basis: 100%; }
.catSection__more { display: block; width: 220px; margin: 20px auto 0; padding: 10px; border: 1px solid #1a365d; border-radius: 4px; color: #1a365d; text-align: center; text-decoration: none; }
.catSection__more:hover { background: #1a365d; color: #fff; }
.catSection__more[aria-busy="true"] { opacity: .6; pointer-events: none; }

7. WordPress 標準の API で作る方法との違い
独自の窓口を作らずに、WordPress に最初からある記事の API(/wp-json/wp/v2/posts)を使う方法もあります。
| 独自の窓口(本記事) | 標準の記事 API | |
|---|---|---|
| 子カテゴリの記事 | cat 指定で含まれる |
categories=2 だけでは含まれない(実測で0件)。categories[terms]=2&categories[include_children]=true と書けば含まれる(実測で16件) |
| 返ってくるもの | そのまま足せる HTML | 記事のデータ(JSON)。HTML は JavaScript で組み立てる |
| 見た目を変えるとき | post-item.php だけ直す |
PHP(最初の5件)と JavaScript(追加分)の2か所を直す |
| カテゴリ名などの付帯情報 | テンプレートの中で自由に取れる | 別に問い合わせるか、_embed などで含める必要がある |
見た目を1か所で管理できるので、本記事では独自の窓口にしました。標準の API で作る場合は、タイトルなどを画面に入れるときに innerHTML ではなく textContent を使うなど、JavaScript 側で文字を安全に扱う必要があります。
8. 実測結果
試験用に、親カテゴリ6つ(子カテゴリあり2つ・日本語名1つ・下書きしか無いもの1つ・記事0件のもの1つ)と子カテゴリ4つ、記事48件(公開44件)を作りました。記事数が5件より少ない・ちょうど5件・多いカテゴリ、2つのカテゴリに属する記事、タイトルに & や引用符を入れた記事、出てはいけない記事(下書き・非公開・予約投稿)を混ぜています。正解の並びは wp-cli で別に出し、画面で「もっと見る」を押し切った結果と1件ずつ突き合わせました。
| ページ・欄 | 正解の件数 | 最初 | 押すたびの件数 | 結果 |
|---|---|---|---|---|
| トップ「お知らせ」(子カテゴリ2つ) | 17 | 5 | 10 → 15 → 17(ボタン消える) | ✅ 正解と一致・重複なし |
| トップ「コラム」(子カテゴリ2つ) | 14 | 5 | 10 → 14(ボタン消える) | ✅ 正解と一致・重複なし |
| トップ「採用」(子カテゴリなし) | 8 | 5 | 8(ボタン消える) | ✅ 正解と一致・重複なし |
| トップ「日本語のカテゴリ」 | 6 | 5 | 6(ボタン消える) | ✅ 正解と一致・重複なし |
| カテゴリページ「お知らせ」→「イベント」欄(ダブルクリックで操作) | 14 | 5 | 10 → 14(ボタン消える) | ✅ 正解と一致・重複なし |
| カテゴリページ「お知らせ」→「メディア掲載」欄 | 3 | 3 | ボタンなし | ✅ |
| カテゴリページ「コラム」→「デザイン」欄(ちょうど5件) | 5 | 5 | ボタンなし | ✅ |
| 子カテゴリが無いカテゴリページ | カテゴリ別の欄は出ず、いつもの一覧だけ | ✅ | ||
| 確かめたこと | 結果 |
|---|---|
| 下書き・非公開・予約投稿が出ない(画面・API、管理者でログインした状態の API も) | ✅ 出ない |
タイトルに <b> を入れた記事 |
✅ 文字のまま表示 |
タイトルに &・引用符を入れた記事(35文字切りを含む) |
✅ 化けずに表示 |
| 日本語名のカテゴリを含め、上のカテゴリ一覧の全リンクを押す | ✅ それぞれの欄へ動く・エラーなし |
| 下書きしか無いカテゴリ・記事0件のカテゴリ | ✅ 一覧にも欄にも出ない(一覧と欄が一致) |
| カテゴリページの2ページ目 | ✅ 欄と「すべての記事」の見出しは出ず、いつもの一覧だけ |
| API が失敗したときに「もっと見る」 | ✅ カテゴリページへ移り、記事が表示される |
| JavaScript が動かない状態で「もっと見る」 | ✅ カテゴリページへ移り、記事が表示される |
| API に、ないカテゴリ | ✅ 404 |
| API に、文字・負の数・大きすぎる値・offset なし | ✅ 400 |
9. 作るときの注意点
続きは「何件目から」で取っています。一覧を開いてから「もっと見る」を押すまでの間に、
・記事が増える(新しく公開される)と、全体が後ろにずれて直前に出ていた記事がもう一度出ます(実測:1件公開してから押すと、5件目の記事が追加分の先頭にもう一度出ました)
・記事が減る(下書きに戻す・非公開にする・削除する・カテゴリを変える)と、全体が前にずれてまだ出ていない記事が1件飛ばされます(実測:表示中の3件目を下書きに戻してから押すと、6件目が出ませんでした)
ふだんは気にならない程度ですが、記事の公開や修正が頻繁なサイトでは気を付けてください。「最後に出した記事の日時と番号」を目印にして続きを取る作りにすると防げる見込みで、いま検証しています(結果が出たらこの記事に追記します)。
「イベント」と「WordPress」の両方に付けた記事は、「お知らせ」と「コラム」の両方の欄に出ます(実測)。1つの欄にだけ出したい場合は、記事に付けるカテゴリを1つにする運用にしてください。
空の欄が並ばないように、公開記事が無いカテゴリ(下書きしか無いカテゴリを含む)は、上のカテゴリ一覧にも欄にも出していません。「未分類」(既定のカテゴリ)も一覧から外しています。出したい場合は
bit_category_sections() の該当箇所を外してください。
bit-template のテーマは、カテゴリごとに URL の規則を作ります。検証では、カテゴリを足した直後はそのカテゴリページが 404 になり、パーマリンクを作り直すと表示されました。「もっと見る」の行き先(JavaScript が動かないとき)もカテゴリページなので、カテゴリを足したら管理画面の「設定 → パーマリンク」で「変更を保存」を押してください。
10. まとめ(ご質問への回答)
home.php・category.php・functions.php に呼び出しを書きます。トップでは親カテゴリごと、カテゴリページでは子カテゴリごとに最新5件が並び、「もっと見る」を押すとページを移らずに5件ずつ増えます。親カテゴリの欄には子カテゴリの記事も入ります。最初の5件も追加分も同じテンプレートで作るので、見た目を変えるときに直すのは1か所です(2章〜6章)。参考(一次ソース)
- WP_Query(カテゴリの指定): https://developer.wordpress.org/reference/classes/wp_query/#category-parameters
- get_categories(): https://developer.wordpress.org/reference/functions/get_categories/
- 独自の REST API の作り方: https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
- 記事の REST API: https://developer.wordpress.org/rest-api/reference/posts/
※本記事の動作は、WordPress 7.1.4(日本語版)/PHP 8.3/MySQL 8.0 の検証環境で、bit-template のテーマ(クラシックテーマ)に部品を足して、2026年11月4日に確認しました。
作成: Seeds Brains(ジェイノーム業務支援AI)