このエントリは、Magento Advent Calendar 2019の20日目です。

今回はGraphQL APIを拡張する方法を紹介しましょう。
MagentoにGraphQL APIが備わっていても、エクステンション側が対応していなければ、GraphQLで利用できません。

GraphQL APIの拡張方法

GraphQL APIを拡張するには、以下の手順が必要です。

  1. スキーマファイルの作成
  2. スキーマの定義
  3. Resolverの定義(必要に応じて)

では早速始めていきましょう。

スキーマファイルを用意する

最初にスキーマファイルを用意する必要があります。
このスキーマファイルは配置する場所とファイル名が決められています。

<エクステンションディレクトリ>/etc/schema.graphqls

という名前のファイルを作成しましょう。

スキーマの定義

次に作成したschema.graphqlsファイルにスキーマを定義していきましょう。

Queryの定義

データ取得を行うQueryは以下のように定義します。

type Query {
    products (
        search: String
        filter: ProductAttributeFilterInput
        pageSize: Int = 20
        currentPage: Int = 1
        sort: ProductSortInput
    ): Products @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products")
}

この例ではQueryの中にproductsという定義を作り、検索をするための設定をしています。
前回までにでてきたQueryで紹介した要素があるのがわかりますね。

productsが取るパラメータ

この定義ではproductsは

  • search
  • filter
  • pageSize
  • currentPage
  • sort

の5つのパラメータを取るという宣言をしているわけです。
filterとsortはIntやStringといったよく目にする名称ではなく、独自の型を使っています。
これは同じようにスキーマ定義で以下のように書きます(例はProductSortInput型です)。

input ProductSortInput  {
    name: SortEnum 
    sku: SortEnum 
    description: SortEnum 
    short_description: SortEnum 
    price: SortEnum 
(中略)
}

SortEnumというのは、Magento/GraphQl/etc/schema,graphqlsで以下のように定義されている型で、要は昇順・降順のことです。

enum SortEnum {
    ASC
    DESC
}

Mutationの定義

Queryと同じように、schema.graphqlsファイルでMutationも定義できます。
書き方はQueryと同じで、"type Mutation" から始まる定義を書くことになります。

Resolverの定義

Resolverというのは先程のQueryの定義のところにあった、

@resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products”)

で定義している内容です。ここで指定されたクラスはGraphQLリクエストを受け取って、関連するクラスを利用しつつ処理を行います。
Resolverの記述方法を解説していると長くなるので、ここから先はDevDocsを見ていただくのが良いでしょう。

既存のスキーマを拡張するには

例えば、独自に実装したエクステンションがあって、そのエクステンションが定義している属性値があるとします。
これらはそのままではGraphQLで利用することはできません。
GraphQLでこれらの属性を利用できるようにするには、schema.graphqlsファイルで定義が必要です。

例えば、下記の例は決済情報に関する型を定義しています。

input PaymentMethodInput {
    code: String! @doc(description:"Payment method code")
    purchase_order_number: String @doc(description:"Purchase order number")
}

Braintree連携の実装では、これに下記のような定義を追加しています。

input PaymentMethodInput {
    braintree: BraintreeInput
    braintree_cc_vault: BraintreeCcVaultInput
}

このように、コア実装で宣言されている内容をエクステンション側から拡張できる仕組みになっています。
うまく拡張・独自定義を行い、HeadlessでMagentoが利用できる領域を増やすと、Magento標準のフロントエンドに依存しないUI/UXのウェブサイトを作りやすくなります。活用してみてください。