月曜日, 5月 19, 2025
ホームWordPresswordpress + astro.jsのヘッドレスCMS構築の道のり #7 カテゴリーとタグの一覧ページroyaltrux

wordpress + astro.jsのヘッドレスCMS構築の道のり #7 カテゴリーとタグの一覧ページroyaltrux

🧠 概要:

概要

この記事では、WordPressとAstro.jsを使用してヘッドレスCMSのカテゴリーとタグの一覧ページを作成する方法が解説されています。具体的には、カテゴリー一覧及び各カテゴリーに属する記事一覧、タグ一覧及び各タグに属する記事一覧を作成する手順が示されています。

要約の箇条書き

  • NuxtからAstro.jsへの移行: Nuxtでの経験を基に、Astro.jsで同様のアプローチを試行する。
  • 注意点: カテゴリーやタグのスラッグは英語に設定しないと404エラーが発生する。
  • カテゴリー一覧ページの作成:
    • /pages/categories/ ディレクトリを作成。
    • APIからカテゴリー情報をフェッチして表示するスクリプトを実装。
  • 各カテゴリー記事一覧:
    • /pages/categories/[slug].astro を作成し、getStaticPathsを使用して静的パスを生成。
    • 該当カテゴリーの投稿をフェッチし、エラーハンドリングを行う。
  • タグ一覧と各タグ記事一覧:
    • タグ一覧ページを /pages/tags/index.astro に実装。
    • 各タグに対するデータ取得と表示を行うための getStaticPaths を使用したスクリプトを作成。

次回は、ページネーション機能の追加についての計画が示されています。

wordpress + astro.jsのヘッドレスCMS構築の道のり #7 カテゴリーとタグの一覧ページroyaltrux

royaltrux

2025年5月19日 17:03

Nuxtでも同じことをやりましたが、Astroでもやってみます!

注意!

記事ページ同様に、各カテゴリー、各tagの slug が日本語だとリンクが上手くいかず、プレビューだと404ページになってしまうので、slug は英語にしてください!

カテゴリー一覧ページの作成

まずは /pages/categories/ のディレクトリと /pages/categories/index.astro を作成します!

そしてスクリプトは

---let categories = [];let error = false; try { const res = await fetch('http://headless.local/wp-json/wp/v2/categories'); if (!res.ok) throw new Error("HTTPエラー"); categories = await res.json();} catch (err) { console.error("記事の取得に失敗しました:", err); error = true;}---

今回は http://headless.local/wp-json/wp/v2/categories で各カテゴリーのデータを取ってきます。
htmlは

<h1>カテゴリー一覧</h1> {error ? ( <p style="color: red;">記事の取得に失敗しました。</p>) : ( <ul> {categories.map((cat) => ( <li> <a href={`/categories/${cat.slug}/`}> {cat.name} ({cat.count}件)        </a>      </li>    ))}  </ul>)}

こんな感じ!
そしてビルドをすると…

はい!ばっちり!
続いて、各カテゴリーの記事一覧です!

各カテゴリーの記事一覧

カテゴリーの記事一覧ページは、/pages/categories/[slug].astro を作成します!
今回は各記事ページ(/pages/blog/[slug].astro)と同様に getStaticPaths を使います。

---export async function getStaticPaths() { try { const res = await fetch('http://headless.local/wp-json/wp/v2/categories'); if (!res.ok) throw new Error(`カテゴリ取得失敗: ${res.status}`); const categories = await res.json(); return categories.map(cat => ({ params: { slug: cat.slug }, props: { category: cat, }, })); } catch (err) { console.error("getStaticPaths エラー:", err); return []; }} let category = null;let posts = [];let fetchError = false; try { category = Astro.props.category; const postRes = await fetch(`http://headless.local/wp-json/wp/v2/posts?categories=${category.id}&_embed`); if (!postRes.ok) throw new Error(`記事取得失敗: ${postRes.status}`); posts = await postRes.json();} catch (err) { console.error("記事取得エラー:", err); fetchError = true;}---

今回はエラー処理をちゃんと入れてみたんで、ちょっと長くなりました。getStaticPaths で使用しているカテゴリーの一覧を取得して、それを props の category に入れてあげます。

で、その Astro.props.category を素に、

http://headless.local/wp-json/wp/v2/posts?categories=${category.id}&_embed

で、各カテゴリーの _embedded 内のデータを取得します。
そして変数 posts に json データを入れてあげて

<body> <h1>カテゴリー: {category?.name || '(不明)'}</h1> {fetchError ? ( <p style="color: red;">記事の取得に失敗しました。</p> ) : posts.length === 0 ? ( <p>このカテゴリーには記事がありません。</p> ) : ( <ul> {posts.map(post => ( <li> <a href={`/blog/${post.slug}/`}> <h2>{post.title.rendered}</h2> </a> </li> ))} </ul> )} <p><a href="/categories/">← カテゴリー一覧に戻る</a></p></body>

html はこんな感じで展開させます!
html側にもエラー処理を書いておきました。

ばっちり😄

タグ一覧と各タグ一覧ページ

Nuxtと同様に全てのタグの一覧ページ、タグの記事一覧ページを作っていきます!
一気にいきましょー

タグ一覧(/pages/tags/index.astro)

index.astroに記述するスクリプトとhtmlです!

---const res = await fetch('http://headless.local/wp-json/wp/v2/tags');let tags = []; try { if (!res.ok) throw new Error(`タグ取得失敗: ${res.status}`); tags = await res.json();} catch (err) { console.error("タグ一覧取得エラー:", err);}---<html lang="ja">  <head>    <meta charset="UTF-8" />    <title>タグ一覧</title>  </head>  <body>    <h1>タグ一覧</h1>    {tags.length === 0 ? (      <p>タグが取得できませんでした。</p>    ) : (      <ul>        {tags.map(tag => (          <li>            <a href={`/tags/${tag.slug}/`}>              {tag.name}({tag.count}件)            </a>          </li>        ))}      </ul>    )}  </body></html>

これまで通りなので、あんまり説明することもないですかな😆

該当タグの投稿一覧(/pages/tags/[slug].astro)

こちらの方は

---export async function getStaticPaths() { try { const res = await fetch('http://headless.local/wp-json/wp/v2/tags'); if (!res.ok) throw new Error(`タグ一覧取得失敗: ${res.status}`); const tags = await res.json(); return tags.map(tag => ({ params: { slug: tag.slug }, props: { tag } })); } catch (err) { console.error("getStaticPaths タグ取得エラー:", err); return []; }} const { tag } = Astro.props; let posts = [];let fetchError = false; try { const res = await fetch(`http://headless.local/wp-json/wp/v2/posts?tags=${tag.id}&_embed`); if (!res.ok) throw new Error(`記事取得失敗: ${res.status}`); posts = await res.json();} catch (err) { console.error("記事取得エラー:", err); fetchError = true;}---<html lang="ja">  <head>    <meta charset="UTF-8" />    <title>{tag.name} の記事一覧</title>  </head>  <body>    <h1>タグ: {tag.name}</h1>    {fetchError ? (      <p style="color: red;">記事の取得に失敗しました。</p>    ) : posts.length === 0 ? (      <p>このタグには記事がありません。</p>    ) : (      <ul>        {posts.map(post => (          <li>            <a href={`/blog/${post.slug}/`}>              <h2>{post.title.rendered}</h2>              <p set:html={post.excerpt.rendered}></p>            </a>          </li>        ))}      </ul>    )}    <p><a href="/tags/">← タグ一覧に戻る</a></p>  </body></html>

こんな感じですかね~🐧
さてビルドしてみましょう!

ばっちり!
そして該当タグの投稿一覧は…

ちりばつ!こっちもOKですね😁

次回はページネーションを作ってみます!

royaltrux



続きをみる


Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -

インモビ転職