2026年7月2日

2026年7月2日

WPGraphQLのMutationで投稿・コメントを作成する実装方法

WPGraphQL を使うと、createPost と createComment という Mutation で WordPress に投稿やコメントを作成できます。投稿の作成には認証と権限が必要で、コメントは WordPress の「ディスカッション設定」に従って受け付けられる、という違いを押さえるのが実装のコツです。この記事では、認証の付け方、2つの Mutation の書き方、エラーの読み方、独自 Mutation を追加するときの安全な書き方までを順に説明します。

前提:WPGraphQL とエンドポイント

WPGraphQL は WordPress に GraphQL API を追加するプラグインで、WordPress.org のプラグインディレクトリから導入できます。近年は WordPress プロジェクトの「カノニカルプラグイン」として扱われるようになっていますが、体制や対応バージョンは変わることがあるため、導入前にプラグインページの更新状況を確認してください(2026年10月現在)。

有効化すると、標準では https://example.com/graphql がエンドポイントになります。管理画面の GraphQL メニューには、クエリを試せる GraphiQL IDE があり、ログイン中の管理者として Mutation を試せます。まずはここで動作を確かめ、そのあと外部のアプリから同じ Mutation を送る、という順番にするとつまずきにくくなります。

本番サイトでいきなり試すと、テスト投稿やテストコメントが公開されてしまうおそれがあります。ステージング環境で試すか、下書き(DRAFT)で作成して確認してください。

投稿を作成する:createPost

投稿の作成は、WordPress の「投稿を作成する権限(edit_posts など)」を持つユーザーとして認証された状態でないと失敗します。GraphiQL IDE では管理者としてログインしているので、そのまま試せます。

mutation CreateDraftPost($title: String!, $content: String) {
  createPost(input: { title: $title, content: $content, status: DRAFT }) {
    post {
      databaseId
      title
      status
    }
  }
}

変数は次のように渡します。

{
  "title": "APIから作成した下書き",
  "content": "<p>本文の段落です。</p>"
}

レスポンスの databaseId が WordPress の投稿 ID です。id フィールドは GraphQL 用のグローバル ID(エンコードされた文字列)なので、wp_posts の ID と照合したいときは databaseId を使います。

status を PUBLISH にすると公開されますが、外部アプリから直接公開すると誤投稿をすぐ取り消せません。運用上は下書きで作成し、管理画面で確認してから公開する流れが安全です。カテゴリーやタグ、アイキャッチの指定にも入力フィールドがありますが、指定方法はスキーマのバージョンで変わることがあるため、GraphiQL IDE のドキュメント(スキーマ表示)で現在の型を確認してください。

外部アプリから認証して送る

外部のサーバーやスクリプトから投稿を作成するなら、WordPress 5.6 以降のコア機能である「アプリケーションパスワード」を使う方法が扱いやすいです。ユーザープロフィール画面で発行し、HTTPS 経由の Basic 認証で送ります。WPGraphQL がアプリケーションパスワードによる認証を受け付けるかはバージョンによって差がある可能性があるため、まず次のような最小のリクエストで確かめてください。

curl -X POST https://example.com/graphql \
  -H "Content-Type: application/json" \
  -u "api-editor:your-app-password" \
  -d '{"query":"mutation($title:String!){createPost(input:{title:$title,status:DRAFT}){post{databaseId status}}}","variables":{"title":"APIテスト"}}'

認証用のユーザーは管理者ではなく、必要最小限の権限(例えば「編集者」や「投稿者」)を持つ専用ユーザーにします。アプリケーションパスワードはソースコードに書かず、環境変数などで渡し、使わなくなったら失効させてください。JWT による認証を使う場合は、WPGraphQL 向けの JWT 認証拡張プラグインがありますが、保守状況を確認したうえで選んでください。

コメントを作成する:createComment

コメントの作成は、投稿の作成とは考え方が異なります。WordPress は未ログインの訪問者にもコメントを許可できるため、createComment も設定次第で認証なしで受け付けます。

mutation AddComment($postId: Int!, $content: String!, $author: String, $authorEmail: String) {
  createComment(
    input: { commentOn: $postId, content: $content, author: $author, authorEmail: $authorEmail }
  ) {
    success
    comment {
      databaseId
      content
    }
  }
}

commentOn にはコメント先の投稿の databaseId(整数)を渡します。返信にしたい場合は parent に親コメントを指定します。

受け付けられるかどうかは、WordPress 側の次の条件で決まります。

  • 対象の投稿でコメントが開いているか(投稿ごとの設定と、古い投稿のコメントを自動で閉じる設定)
  • 「ユーザー登録してログインしたユーザーのみコメントをつけられるようにする」が有効か(オプション名 comment_registration)
  • 「コメントの投稿者の名前とメールアドレスの入力を必須にする」が有効か(オプション名 require_name_email)。有効なら未ログイン時は author と authorEmail が必要
  • 承認制の設定。承認待ちになったコメントは、未ログインのリクエストでは comment が返らないことがある

最後の点は「success が true なのに comment が null」という形で現れることがあります。管理画面のコメント一覧で、承認待ちとして保存されているかを確認してください。

スパムと個人データへの配慮

認証なしでコメントを受け付ける API は、そのままでは機械的なスパムの入口になります。Akismet などのスパム対策プラグインが API 経由のコメントにも効いているかは、テスト投稿を送って管理画面で判定結果を見るのが確実な確認方法です。加えて、承認制にする、Web サーバーや WAF でエンドポイントへのリクエスト数を制限する、といった対策を組み合わせます。

コメントでは名前やメールアドレスという個人データを受け取ります。フロントエンドのフォームにも、WordPress サイトと同じくプライバシーポリシーへのリンクと、何のために保存するのかの説明を置いてください。

エラーの読み方

GraphQL は、エラーがあっても HTTP ステータス 200 でレスポンスを返すことが多く、本文の errors 配列を見ないと失敗に気づけません。クライアント側では「errors があれば失敗」として扱ってください。よくある症状を、起こりやすい順に並べます。

  1. 権限がないというメッセージ:認証が通っていないか、ユーザーの権限が足りません。curl で -u を外した場合と付けた場合でメッセージが変わるかを比べ、変わらなければ認証ヘッダーがサーバーまで届いていない可能性があります。CGI/FastCGI 構成では Authorization ヘッダーが PHP に渡らないことがあり、サーバー設定の見直しが必要です
  2. 入力の型エラー:commentOn に文字列のグローバル ID を渡した、status に小文字を渡した、などです。エラー文に期待される型が書かれているので、GraphiQL IDE のスキーマ表示と照らし合わせます
  3. コメントが閉じている・必須項目が足りない:前述のディスカッション設定を確認します
  4. 詳細が出ない内部エラー:WPGraphQL の設定画面にあるデバッグモードを、ステージング環境で一時的に有効にすると、詳しいメッセージが返るようになります。本番では無効に戻してください

独自の Mutation を追加する

「下書きのメモだけを作らせたい」のように、標準の createPost より狭い操作だけを公開したい場合は、register_graphql_mutation() で独自の Mutation を定義します。子テーマの functions.php よりも、専用のプラグインか mu-plugin に置くほうが、テーマ変更の影響を受けません。

<?php
add_action( 'graphql_register_types', function () {
	register_graphql_mutation( 'createDraftNote', [
		'inputFields'         => [
			'title'   => [
				'type'        => [ 'non_null' => 'String' ],
				'description' => 'メモのタイトル',
			],
			'content' => [
				'type'        => 'String',
				'description' => 'メモの本文',
			],
		],
		'outputFields'        => [
			'postId' => [
				'type'    => 'Int',
				'resolve' => function ( $payload ) {
					return $payload['postId'];
				},
			],
		],
		'mutateAndGetPayload' => function ( $input ) {
			if ( ! current_user_can( 'edit_posts' ) ) {
				throw new \GraphQL\Error\UserError( 'この操作を行う権限がありません。' );
			}

			$post_id = wp_insert_post( [
				'post_title'   => sanitize_text_field( $input['title'] ),
				'post_content' => wp_kses_post( $input['content'] ?? '' ),
				'post_status'  => 'draft',
				'post_type'    => 'post',
			], true );

			if ( is_wp_error( $post_id ) ) {
				throw new \GraphQL\Error\UserError( $post_id->get_error_message() );
			}
			return [ 'postId' => $post_id ];
		},
	] );
} );

ここで大切なのは、mutateAndGetPayload の先頭で current_user_can() による権限チェックを行い、入力を sanitize_text_field() や wp_kses_post() で整えてから保存していることです。GraphQL のスキーマで型を決めても、文字列の中身までは検証されません。UserError で投げたメッセージはクライアントに返るので、内部情報を含めないようにします。

同一オリジンのブラウザから Cookie 認証で Mutation を送る構成では、CSRF 対策(nonce の扱い)も必要になります。WPGraphQL での具体的な扱いはバージョンで変わる可能性があるため、公式ドキュメントで確認してください。

まとめ

  • createPost は投稿を作成する権限を持つユーザーとして認証が必要。外部アプリからは、最小権限の専用ユーザーとアプリケーションパスワードで HTTPS 経由で送る
  • 作成は下書き(DRAFT)にして、管理画面で確認してから公開する運用が安全
  • createComment はディスカッション設定に従う。commentOn には投稿の databaseId を渡す
  • 認証なしのコメント受け付けはスパム対策とリクエスト制限を組み合わせ、個人データの扱いをプライバシーポリシーで示す
  • GraphQL は HTTP 200 でも errors が返ることがある。独自 Mutation では権限チェックとサニタイズを省かない

お気軽にご相談ください

お見積りへ お問い合わせへ
▲