Next.jsとWordPressのREST APIで記事検索を実装する
2024/11/27 (水) - 09:00 JavaScriptPHP&CMS
WordPressでヘッドレスCMSを作成する時、記事検索結果ページを動的に実装したのでそのメモです。環境は以下を想定。
- WordPress 6.5
- Next.js v14.x(App Router)
まずWordPressのREST APIのエンドポイントを指定しておきます。例では.envファイルにはAPIのエンドポイントを指定しました。これは記事一覧や詳細でも同じAPIを呼び出します。
BLOG_JSON_URL='https://example.com/wp-json/wp/v2/posts/'
BLOG_NAME='あいかの日記帳'
次に検索ボックスのinput要素を用意します。name属性はsとしておき、GETパラメータで検索ワードを送信する形にします。
<form method="get" action="/search/">
<input type="search" value="" placeholder="キーワードを入力" name="s" id="s" />
</form>
検索結果一覧ページです。/search/page.js
とし、以下のざっくりとしたコードです(アイキャッチがない場合の処理やエラーなど詳細は省いています)。記事詳細などはSSG
でいいのですが、この部分だけはSSRで動的レンダリングする想定で組んでおります。fetchするときAPIにsearchパラメータでキーワードを指定することで、該当するキーワードに該当する記事のみを取得することが出来ます。
import Link from 'next/link';
async function getPostSearch(url) {
const res = await fetch(url);
return res.json()
}
async function getPostSearchTotal(url) {
const count = await fetch(url).
then((res) => {return parseInt(res.headers.get('X-WP-Total'))});
return count;
}
export default async function SearchPage( props ) {
const search = props.searchParams.s;
const url = `${process.env.BLOG_JSON_URL}?_embed&search=${search}`;
const posts = await getPostSearch(url);
const length = await getPostSearchTotal(url);
if(!length){
return (
<div>
<h1>{search}は見つかりませんでした</h2>
<p><Link href='/'>一覧に戻る</Link></p>
</div>
)
}else{
return (
<div>
<h1>{search} の検索結果:{ length }件</h1>
<ul>
{ posts.map((post) =>
<li key={post.id}>
<Link href={`/${post.slug}`}>
<img src={post._embedded['wp:featuredmedia'][0].source_url} width="100" height="100" alt="" loading="lazy" />
<p>{post.title.rendered}</p>
</Link>
</li>
)}
</ul>
</div>
);
}
}
ポイントとしてはWordPressからJSONを受け取る際にレスポンスヘッダーのX-WP-Total
から記事数を取得します。また、この例ではアイキャッチ画像を取得するため、エンドポイントに_embed
パラメータを指定しています。
おしまい♥
おすすめ記事
- Next.js(App Router)で、Fetch APIを使った静的ファイル生成(SSG)でヘマした
- PHPでClaude APIを使ってみた。
- npmのキャッシュクリアとメンテナンス
- Astro&microCMSで1ページ内にカテゴリごとの記事一覧を表示する
- Reactで簡易的なカレンダーを作成
トラックバック & ピンバック
- この記事へのトラックバックURI:
- https://weblog.walk-life.me/nextjs_wordpress_search/trackback/