Tailwind Logo

XM Cloud で管理している記事の RSS フィードを作成する(前編)

XM CloudNext.js

公開日: 2024-07-04

今回は XM Cloud のコンテンツに関して、GraphQL から記事の一覧を取得して RSS フィードを作成する手順を紹介します。

前提条件

今回は RSS フィードのサンプルを作ることを前提として、最小限のフィールドとサンプルで作成をしていきます。実際のページテンプレートに同様のフィールドを設定すれば、記事だけでなく様々な RSS を実装することが可能です。

前提条件は以下のようにします。

  • RSS フィードとして、対象のテンプレートの以下の項目を取得します
    • タイトル
    • 概要
    • 公開日
    • URL
    • 画像
  • Next.js App Router の仕組みを利用して実装する

サンプルのコードに関しては https://github.com/haramizu/sitecoredemo-jp のリポジトリに実装していきます。

JSS 22.0 の Next.js は 14.1 でサイト全体としては Page Router で構築されています。Page Router と App Router は共存することが可能です。RSS に関しては GraphQL を利用してデータを取得、XML でデータを返すという実装をしたいと考えています。そこで今回は App Router で実装していきます。

News テンプレートの作成

テンプレートの作成にあたって、Page テンプレートを複製して新しく Article テンプレートを作成します。/sitecore/templates/Project/Tailwindcss/Page のテンプレートを右クリックして、Duplicate をクリックしてください。

xmcrss01.png

今回は News というテンプレートで作成します。既存の Title はそのまま利用する形として、以下の3つの項目を追加してください。

  • Description - Multi-line Text
  • PublishDate - Datetime
  • Image - Image

これでテンプレートが完成です。実装においては、News のテンプレートを利用してアイテムを作成することができるように、どのタイプの下に作れるのか、なども定義する必要がありますが、今回は RSS フィードを作成するのが目的のため省略します。

サンプルのアイテムを作成する

今回は5つほどの記事をサンプルとして作成をして、RSS として表示するように作っていきます。実際に対象となるコンテンツの本数が増えた場合は、複数回に分けて GraphQL でデータを取得する必要が出てきますが、RSS の最小限のサンプルを作るのが今回のコンセプトのため省略します。

今回は RSS のサンプルを以下のような形でいくつかのページの下に作成をしてみました。上記で作成した News テンプレートを利用して、いくつかのパスでアイテムが作成されているのがわかります。

xmcrss02.png

Postman を利用してデータを取得

上記のアイテムに関して、GraphQL からデータを取得するクエリを作成していきます。条件は以下の通りとなります。

  • News テンプレート ID のコンテンツの一覧を取得
  • 英語のアイテムを取得
  • アイテムのフィールドのデータ表示
  • 日付順に並べ替える

それでは実際にクエリを作成していきます。

News コンテンツ一覧の取得

問い合わせとしては、Sitecore が管理しているアイテムに対して News テンプレートとして利用している ID で問い合わせをします。以下の問い合わせとなります。

GraphQL
query Search ($templateId: String!){
    search(
        where: {
            name: "_templates"
            value: $templateId
            operator: EQ
        }
    ) {
        total
    }
}

今回は $templateId 対して、GraphQL Variables として以下のデータを設定しています。

JSON
{
    "templateId": "B9453B23-0E09-4D98-99C0-EAA0F16DD6DA"
}

以下の結果を取得しました。

JSON
{
    "data": {
        "search": {
            "total": 6
        }
    }
}

5つアイテムを作成したはずですが、このテンプレートで作っているアイテムの数は 6 となっています。これは後ほど修正します。

英語のアイテムを取得

続いて対象となるコンテンツを英語飲みに絞り込みをします。言語を切り替えて別の RSS を作成する形も考えられるため、この値も GraphQL Variables として持つように以下のように変更します。

JSON
{
    "language": "en",
    "templateId": "B9453B23-0E09-4D98-99C0-EAA0F16DD6DA"
}

続いて言語の絞り込みをする際には、where でテンプレート ID に対して AND のルールを追加して、言語に関してしていするようにします。

GraphQL
query Search($language: String!, $templateId: String!) {
    search(
        where: {
            name: "_templates"
            value: $templateId
            operator: EQ
            AND: { name: "_language", value: $language, operator: EQ }
        }
    ) {
        total
    }
}

結果は同じく 6 が今回も返されました。実際に他の言語のコンテンツを作成しても、Total の数字が変わらない形になりますので、絞り込みができているかの確認は CMS 上で別の言語を作成して確認をしてください。

アイテムのフィールドを追加する

アイテムのデータを取得する際の GraphQL に関して、項目を今回は絞って実行したいと思います。まずは id および URL を取得するようにします。

GraphQL
query Search($language: String!, $templateId: String!) {
    search(
        where: {
            name: "_templates"
            value: $templateId
            operator: EQ
            AND: { name: "_language", value: $language, operator: EQ }
        }
    ) {
        total
        results {
            id
            url {
                hostName
                path
            }
        }
    }
}

これで実行をすると6つのアイテムの path を確認することができます。結果を見ると、実は以下のアイテムの取得ができていることがわかります。

JSON
{
  "id": "D6C15B8571874F96A684CA8655E615AA",
  "url": {
    "hostName": "xmcloudcm.localhost",
    "path": "/en/sitecore/templates/Project/Tailwindcss/PageType/News/__Standard-Values"
  }
}

つまりテンプレートを作成して、そのテンプレートの定義の __Standard-Values のアイテムが同じ ID を利用していることになります。そこで、今回はコンテンツツリーの配下のアイテムのみを取得するように、Where に siteRootId を追加して変数として持てるようにします。

GraphQL
query Search($language: String!, $siteRootId: String!, $templateId: String!) {
    search(
        where: {
            name: "_templates"
            value: $templateId
            operator: EQ
            AND: [
                { name: "_path", value: $siteRootId, operator: CONTAINS }
                { name: "_language", value: $language, operator: EQ }
            ]
        }
    ) {

この時の Variables 配下の通りです。

JSON
{
    "language": "en",
    "siteRootId": "E66EE43B-398B-486E-9F7F-5FE36A4093D3",
    "templateId": "B9453B23-0E09-4D98-99C0-EAA0F16DD6DA"
}

この _path の value に関しては、コンテンツツリーのトップのアイテムの ID を利用しています。これにより、Article のアイテムでもツリーの配下のみのデータを取る形となります。

続いて必要なフィールドのデータを取るために、results の下を以下のように書き換えます。

GraphQL
results {
    id
    url {
        hostName
        path
    }
    title: field(name: "Title") {
        value
    }
    publishDate: field(name: "PublishDate") {
        value
    }
    description: field(name: "Description") {
        value
    }
    image: field(name: "Image") {
        jsonValue
    }
}

これで RSS で必要となるデータが揃ってきました。

公開日順で取得

取得しているデータのうち、publishDate の項目を新着順にするための並び順を Where の中に記述をします。

以下が、完成した GraphQL の問い合わせとなります。

GraphQL
query Search($language: String!, $siteRootId: String!, $templateId: String!) {
    search(
        where: {
            name: "_templates"
            value: $templateId
            operator: EQ
            AND: [
                { name: "_path", value: $siteRootId, operator: CONTAINS }
                { name: "_language", value: $language, operator: EQ }
            ]
        }
        orderBy: { direction: DESC, name: "publishDate" }
    ) {
        total
        results {
            id
            url {
                hostName
                path
            }
            title: field(name: "Title") {
                value
            }
            publishDate: field(name: "PublishDate") {
                value
            }
            description: field(name: "Description") {
                value
            }
            image: field(name: "Image") {
                jsonValue
            }
        }
    }
}

まとめ

書いていると GraphQL でデータを取得するまででそれなりの長さになってしまいました。そこで、今回は RSS で必要となるデータを GraphQL を利用して取得するところまでとさせていただきます。次回は、データを取得したあとに、RSS のデータを返すところまで仕上げていきます。

関連記事

関連タグ