2026年5月20日

2026年5月20日

WordPressプラグインでREST APIエンドポイントを追加する方法

はじめに

WordPress REST APIにカスタムエンドポイントを追加すると、外部アプリ・モバイルアプリ・JavaScriptからWordPressのデータを取得・操作できます。register_rest_route() を使ったエンドポイントの作成から認証・レスポンス設計まで解説します。

症状・原因

  • WordPressのデータを外部アプリやJavaScriptから取得したい
  • 独自のAPIエンドポイントをWordPressに追加したい
  • REST APIのレスポンスに独自フィールドを追加したい
  • エンドポイントへのアクセスを認証で制限したい

解決手順

ステップ1:基本的なエンドポイントを作成する

// プラグインファイル — カスタムREST APIエンドポイントを登録
add_action('rest_api_init', function(): void {

    // GET エンドポイント: /wp-json/myplugin/v1/posts
    register_rest_route('myplugin/v1', '/posts', [
        'methods'             => \WP_REST_Server::READABLE, // GET
        'callback'            => 'myplugin_get_posts',
        'permission_callback' => '__return_true', // 認証不要(公開)
        'args'                => [
            'count' => [
                'type'              => 'integer',
                'default'           => 5,
                'minimum'           => 1,
                'maximum'           => 100,
                'sanitize_callback' => 'absint',
            ],
        ],
    ]);

    // POST エンドポイント: /wp-json/myplugin/v1/note
    register_rest_route('myplugin/v1', '/note', [
        'methods'             => \WP_REST_Server::CREATABLE, // POST
        'callback'            => 'myplugin_create_note',
        'permission_callback' => fn() => current_user_can('publish_posts'),
    ]);
});

ステップ2:コールバック関数を実装する

// GET コールバック
function myplugin_get_posts(\WP_REST_Request $request): \WP_REST_Response {
    $count = $request->get_param('count');

    $posts = get_posts([
        'numberposts' => $count,
        'post_status' => 'publish',
    ]);

    $data = array_map(function(\WP_Post $post): array {
        return [
            'id'      => $post->ID,
            'title'   => $post->post_title,
            'excerpt' => get_the_excerpt($post),
            'url'     => get_permalink($post),
            'date'    => $post->post_date,
        ];
    }, $posts);

    return new \WP_REST_Response($data, 200);
}

// POST コールバック
function myplugin_create_note(\WP_REST_Request $request): \WP_REST_Response|\WP_Error {
    $title   = sanitize_text_field($request->get_param('title') ?? '');
    $content = wp_kses_post($request->get_param('content') ?? '');

    if (empty($title)) {
        return new \WP_Error('missing_title', 'タイトルは必須です', ['status' => 400]);
    }

    $post_id = wp_insert_post([
        'post_title'   => $title,
        'post_content' => $content,
        'post_status'  => 'publish',
        'post_type'    => 'note',
    ]);

    if (is_wp_error($post_id)) {
        return new \WP_REST_Response(['error' => $post_id->get_error_message()], 500);
    }

    return new \WP_REST_Response(['id' => $post_id, 'title' => $title], 201);
}

ステップ3:URLパラメーターを使うエンドポイント

// /wp-json/myplugin/v1/posts/123
register_rest_route('myplugin/v1', '/posts/(?P<id>\d+)', [
    'methods'             => \WP_REST_Server::READABLE,
    'callback'            => function(\WP_REST_Request $req): \WP_REST_Response|\WP_Error {
        $post = get_post((int) $req->get_param('id'));

        if (!$post || $post->post_status !== 'publish') {
            return new \WP_Error('not_found', '投稿が見つかりません', ['status' => 404]);
        }

        return new \WP_REST_Response([
            'id'      => $post->ID,
            'title'   => $post->post_title,
            'content' => apply_filters('the_content', $post->post_content),
        ], 200);
    },
    'permission_callback' => '__return_true',
    'args'                => [
        'id' => [
            'validate_callback' => fn($v) => is_numeric($v),
        ],
    ],
]);

ステップ4:認証(Application Password)を設定する

WordPress 5.6以降で標準機能:
ユーザー → プロフィール → アプリケーションパスワード
→「新しいアプリケーションパスワードの名前」に入力
→「追加」→ パスワードをコピー(再表示不可)

APIリクエストの認証:
Authorization: Basic base64(username:app-password)
# WP-CLIでエンドポイントをテスト
wp rest myplugin/v1/posts list

# curlでGETリクエスト(公開エンドポイント)
curl https://example.com/wp-json/myplugin/v1/posts?count=3

# curlでPOSTリクエスト(認証必要)
curl -X POST https://example.com/wp-json/myplugin/v1/note \
  -u "username:xxxx xxxx xxxx xxxx xxxx xxxx" \
  -H "Content-Type: application/json" \
  -d '{"title":"テストノート","content":"本文"}'

# 登録済みルートを確認
wp eval "print_r(rest_get_server()->get_routes());" | grep myplugin

ステップ5:既存エンドポイントにフィールドを追加する

// 既存の投稿エンドポイントにカスタムフィールドを追加
add_action('rest_api_init', function(): void {
    register_rest_field('post', 'view_count', [
        'get_callback'    => fn(array $post): int => (int) get_post_meta($post['id'], '_view_count', true),
        'update_callback' => fn(int $count, \WP_Post $post): void => update_post_meta($post->ID, '_view_count', $count),
        'schema'          => ['type' => 'integer', 'description' => '閲覧数'],
    ]);
});

注意事項

  • permission_callback__return_true を設定すると認証なしで誰でもアクセスできます。機密データを返すエンドポイントには必ず認証を設定してください
  • REST APIエンドポイントのURLは /wp-json/名前空間/バージョン/リソース の形式にしてください
  • 入力値は必ず sanitize_text_field()absint() でサニタイズしてください

まとめ

register_rest_route()rest_api_init フックで呼び出すことでカスタムエンドポイントを追加できます。コールバックは WP_REST_Response を返し、エラー時は WP_Error を返します。Application Passwordで認証を実装すれば安全なAPIが構築できます。

お気軽にご相談ください

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