ドキュメント

コンテンツのタグやカテゴリを扱う

本チュートリアルでは、タグやカテゴリを参照コンテンツを使って設定し、特定のタグやカテゴリを含むコンテンツを取得する方法を説明します。

hacoCMSのAPIでタグやカテゴリを扱う方法

タグやカテゴリは、以下のようなタイプのフィールドによって扱うことができます。

  • テキストフィールド(カンマ区切り等で入力)
  • セレクトフィールド(選択肢の中から選択)
  • 参照フィールド(別APIのコンテンツを選択)

それぞれの方法の利点と欠点について説明します。

テキストフィールドで扱う

タグやカテゴリをテキストフィールドで扱うと、コンテンツの作成・編集時に任意に設定させることができます。

一方で、任意に設定できてしまうことで、コンテンツに設定されているタグやカテゴリの一覧が欲しい場合には、全てのコンテンツからタグやカテゴリを集める必要があります。また、複数のタグやカテゴリを設定できるようにする場合、区切りに使う文字を予め決めておき、入力時に守って貰わなければなりません。さらに、APIの検索フィルターで特定のタグやカテゴリのコンテンツを検索する場合に、区切り文字の扱いに注意が必要になります。

セレクトフィールドで扱う

タグやカテゴリをセレクトフィールドで扱うと、予め選択肢として設定した中から選択させることができます。

一方で、選択肢の一覧を取得することはできないため、フロントエンドの実装側でハードコードするか、コンテンツに設定されているものを収集する必要があります。また、新たなタグやカテゴリを設定する場合は、APIスキーマのフィールド設定で選択肢に追加してからコンテンツに設定する必要があります。

参照フィールドで扱う

タグやカテゴリをコンテンツとして登録しておくAPIが別途必要になりますが、参照フィールドで扱うこともできます。参照フィールドを使う場合、タグやカテゴリの選択肢が「コンテンツ」になるため、タグやカテゴリの名称とそれに付随する情報(例:URLに使用するためのスラッグ)を一緒に登録しておくことができます。

以上のうち、最も柔軟な使い方ができる参照フィールドによってタグやカテゴリを扱う方法について詳しく説明します。

参照フィールドでの実現方法

ここではブログの記事にタグを付与し、各タグの付いた記事を一覧できるように、参照フィールドを使って実装する方法を説明します。

hacoCMSでのAPI設定

  1. タグAPIをリスト形式で作成します。APIスキーマには最低限、タグ名を含めます。
  2. (既存の、あるいは新規に作成した)記事APIのスキーマにタグのフィールドを参照フィールドで追加し、フィールド設定の「参照するコンテンツ」でタグAPIを選択します。複数選択可にする場合はあわせて「複数のコンテンツを参照をする」にチェックを入れてください。

新しいタグを記事に設定するには、タグAPIに設定したいタグをコンテンツとして作成した上で、記事コンテンツのタグフィールドにタグAPIのタグコンテンツを追加します。

フロントエンドの実装

必要なタグや記事をhacoCMSのAPIを通じて取得するように実装します。APIの仕様については「APIリファレンス」をご確認ください。また、ご使用の言語にSDKが用意されている場合はそちらを使用することもできます。SDKはGitHubや各種パッケージレジストリで公開していますので適宜ご活用ください。

タグ一覧の取得

タグAPIのコンテンツ一覧取得エンドポイントにGETリクエストを送ることで、タグの一覧を取得することができます。

特定のタグが付与された記事一覧の取得

記事APIのコンテンツ一覧取得エンドポイントに、検索フィルタークエリでタグの参照フィールドに対する条件を指定してGETリクエストを送ることで、指定の条件に合ったタグが付与された記事の一覧を取得することができます。

例えば、タグAPIにタグ名のフィールドがnameというIDで、entriesという記事APIにタグAPIを参照する複数選択可のフィールドがtagsというIDで設定されている場合を考えます。「日記」というタグ名のタグが付いた記事の一覧を取得するには、記事APIのコンテンツ一覧取得エンドポイントにq=tags[*].name[eq]:日記を(URLエンコードして)クエリ文字列に加えたURLにGETリクエストを送ります。もし、記事のタグが複数選択不可の場合は、[*]を除いたq=tags.name[eq]:日記を(URLエンコードして)クエリ文字列に加えます。

この例におけるリクエストURLは以下のようになります。

複数タグ リクエストURL例(URLエンコード前)
https://〈サブドメイン〉.hacocms.com/api/v1/entries?q=tags[*].name[eq]:日記
不可 https://〈サブドメイン〉.hacocms.com/api/v1/entries?q=tags.name[eq]:日記

Next.jsでの実装例

ここでは、タグの一覧ページと各タグが付与された記事の一覧ページを、JavaScript/TypeScript用のSDK(hacocms-js-sdk)を使ってNext.jsで実装する例を説明します。Next.jsの静的サイト生成(SSG)でhacoCMSを使う​チュートリアルの続きとして説明しますので、そちらを先にご覧いただいておくことをお勧めします。

Step 1. hacoCMSのAPIスキーマ設定

まず、タグAPIを以下のような設定で作成してください。

  • API名:タグ(任意)
  • エンドポイント:tags
  • APIの型:リスト形式
  • APIスキーマ:次の表を参照
フィールドタイプ フィールド名(任意) フィールドID
テキストフィールド タグ name
テキストフィールド スラッグ slug

タグAPIを作成したら、いくつかのタグを作成しておきましょう。

次に、記事APIにタグを設定するフィールドを以下のような設定で追加してください。

フィールドタイプ フィールド名(任意) フィールドID フィールド設定
参照フィールド タグ tags 参照するコンテンツ:タグ
複数のコンテンツを参照をする:☑チェックする

タグのフィールドを追加したら、タグを設定した記事をいくつか用意してみましょう。

Step 2. タグの一覧表示

ここでは、タグAPIを使ってタグの一覧を取得し、トップページに表示するようにします。

まず、pages/index.jsgetStaticProps関数に以下の行を追加し、返り値のpropstagsを追加してください。

  // タグ API /tags に GET リクエストを送信し、タグ一覧を取得します
  const tags = (await client.getList(Object, '/tags', { s: SortQuery.build('slug') })).data

この関数のreturn文は次のようになります。

  return {
    props: {
      recentEntries,
      tags,
    },
  }

次に、Homeの関数に変更を加えます。引数のオブジェクトからtagsを受け取るようにし、返り値に以下のようなタグ一覧の表示を加えます。

    <h2>Tags</h2>
    <ul>
      {tags.map((tag) => (
        <li key={tag.id}>
          <Link href={`/tags/${tag.slug}`}>{tag.name}</Link>
        </li>
      ))}
    </ul>

サイトをビルドして確認サーバを立ち上げ(npm run build && npm run start)、ブラウザでトップページにアクセスして、タグの一覧が表示されることを確認してください。

Step 3. タグページの作成

pages/tags/[slug].jsファイルを作成し、以下のようなコードを書いてください。

import { HacoCmsClient, SortQuery } from 'hacocms-js-sdk'
import Link from 'next/link'

// (1) プロジェクト基本設定画面のサブドメインに置き換えてください。
const PROJECT_SUBDOMAIN = 'SUBDOMAIN'

// (2) プロジェクトの Access-Token に置き換えてください。
const PROJECT_ACCESS_TOKEN = 'ACCESS_TOKEN'

const client = new HacoCmsClient(`https://${PROJECT_SUBDOMAIN}.hacocms.com`, PROJECT_ACCESS_TOKEN)

/** すべてのタグページの [slug] を返す */
export async function getStaticPaths() {
  const paths = (await client.getList(Object, '/tags')).data.map(({ slug }) => ({ params: { slug } }))
  return {
    paths,
    fallback: false,
  }
}

/** タグページ /tags/[slug] の生成に使用するデータを返す */
export async function getStaticProps({ params }) {
  // [slug] からタグコンテンツを取得
  const [tag] = (await client.getList(Object, '/tags', {
    q: `slug[eq]:${params.slug}`,
  })).data

  // 指定のタグを含む記事を取得
  const entries = (await client.getList(Object, '/entries', {
    q: `tags[*].slug[eq]:${params.slug}`,
    s: SortQuery.build(['createdAt', 'desc']),
  })).data

  return {
    props: {
      tag,
      entries,
    },
  }
}

const Tag = ({ tag, entries }) => (
  <>
    <h1>{tag.name}</h1>
    <ul>
      {entries.map((entry) => (
        <li key={entry.id}>
          <Link href={`/post/${entry.id}`}>{entry.title}</Link>
        </li>
      ))}
    </ul>
    <Link href="/">Back to Home</Link>
  </>
)

export default Tag

ポイントとなっているのはgetStaticProps関数のentries変数への代入文で、これが特定のタグが付与された記事一覧の取得方法をSDKを用いて実装したものになります。

サイトをビルドして確認サーバを立ち上げ(npm run build && npm run start)、ブラウザでトップページにアクセスして、タグのリンクが辿れるようになり、そのタグの記事一覧が表示されることを確認してください。