WordPressのAbilities APIが使えそう。プラグイン機能を“発見しやすくする”新しいまとめ方

はじめに

WordPressのプラグインやテーマを作っていると、処理そのものより「その機能をどう外から呼べる形にしておくか」で悩むことがあります。管理画面ボタン用の関数、REST API用のエンドポイント、将来の自動化用フックがばらばらに増えていくと、あとから見返したときにつらくなりがちです。

WordPress 6.9で入ったAbilities APIは、そうした機能を“能力”として登録し、見つけやすく、再利用しやすくまとめるための新しい土台です。2025年11月のDeveloper BlogとMake/Coreのdev noteでも、PHP、REST API、将来の自動化やAI連携まで見据えた統一的な仕組みとして紹介されています。

この記事では、Abilities APIの考え方をざっくりつかみつつ、まずはプラグイン内の処理を1つAbilityとして登録し、管理用途の小さな機能を整理する実例まで見ていきます。

機能やライブラリの概要

Abilities APIは、WordPress 6.9以降で使える新しい共通APIです。Developer Handbookでは、Abilitiesを「明確な入力・出力・権限・実行ロジックを持つ、個別の機能単位」と説明しています。

ポイントは、単なる関数登録ではなく、次の情報をまとめて持てることです。

  • 何という名前の機能か
  • 何を入力として受け取るか
  • 何を返すか
  • どの権限で実行できるか
  • どのカテゴリに属するか

Make/Coreのdev noteでは、主なPHP APIとしてwp_register_ability()wp_get_ability()wp_get_abilities()などが案内されています。さらに、meta.show_in_restを有効にすると、登録したAbilityをREST API経由で参照・実行できる構成も取れます。

つまり、今まで散らばりがちだった「機能の定義」と「外部公開の窓口」を、少し揃えやすくなるわけです。

基本の使い方

最初は、投稿タイプごとの公開件数を返す小さなAbilityを登録してみます。このコードでは、カテゴリ登録のあとにAbility本体を定義しています。

PHP
<?php
/**
 * Plugin Name: Article Dashboard Abilities
 */

add_action( 'wp_abilities_api_categories_init', function () {
    wp_register_ability_category(
        'article-tools',
        array(
            'label'       => __( 'Article Tools', 'article-dashboard' ),
            'description' => __( 'Editorial helper abilities.', 'article-dashboard' ),
        )
    );
} );

add_action( 'wp_abilities_api_init', function () {
    wp_register_ability(
        'article-dashboard/get-post-count',
        array(
            'label'               => __( 'Get post count', 'article-dashboard' ),
            'description'         => __( 'Returns publish counts for a given post type.', 'article-dashboard' ),
            'category'            => 'article-tools',
            'input_schema'        => array(
                'type'       => 'object',
                'properties' => array(
                    'post_type' => array(
                        'type' => 'string',
                        'enum' => array( 'post', 'page' ),
                    ),
                ),
                'required'   => array( 'post_type' ),
            ),
            'output_schema'       => array(
                'type'       => 'object',
                'properties' => array(
                    'post_type' => array( 'type' => 'string' ),
                    'count'     => array( 'type' => 'integer' ),
                ),
                'required'   => array( 'post_type', 'count' ),
            ),
            'permission_callback' => function () {
                return current_user_can( 'edit_posts' );
            },
            'execute_callback' => function ( array $input ) {
                $counts = wp_count_posts( $input['post_type'] );

                return array(
                    'post_type' => $input['post_type'],
                    'count'     => (int) $counts->publish,
                );
            },
        )
    );
} );

このコードでやっていることは、ばらけがちな情報を1か所に集めているだけです。Ability名、権限、入力と出力の形、実行処理がまとまっているので、あとから読むと何をする機能か追いやすくなります。

単純な関数だけでも動きますが、Schemaまで置いておくと、将来的にREST API経由で呼ぶときや、他の開発者が触るときにかなり親切です。

便利な使いどころ

Abilities APIが効きやすいのは、「管理系の小さな処理が増えていく」プラグインです。

  • 投稿集計やステータス確認のようなダッシュボード補助
  • 定型のメンテナンス処理
  • サイト設定やメタ情報を返す読み取り系API
  • 将来的に外部ツールや自動化から呼びたい処理

たとえば、編集部向けの独自ダッシュボードを作っているとします。公開件数取得、アイキャッチ未設定記事の一覧取得、予約投稿チェックなどの機能が増えてくると、個別のAJAXやRESTエンドポイントだけで整理するのが少しずつ苦しくなります。

そういうとき、各処理をAbilityとして登録しておくと、「このサイトにどんな実行可能機能があるか」を揃った形で扱えます。Developer Blogでも、Abilities APIは“discoverable”な機能定義として位置付けられています。実務目線では、チーム内での把握や再利用がしやすくなる、という理解がいちばん分かりやすいと思います。

応用コード

次は、登録したAbilityをREST APIからも扱えるようにする例です。このコードではmeta.show_in_restを有効にし、未設定アイキャッチの記事を返すAbilityにしています。

PHP
add_action( 'wp_abilities_api_init', function () {
    wp_register_ability(
        'article-dashboard/list-posts-without-thumbnail',
        array(
            'label'               => __( 'List posts without thumbnail', 'article-dashboard' ),
            'description'         => __( 'Returns published posts that do not have a featured image.', 'article-dashboard' ),
            'category'            => 'article-tools',
            'input_schema'        => array(
                'type'       => 'object',
                'properties' => array(
                    'limit' => array(
                        'type'    => 'integer',
                        'minimum' => 1,
                        'maximum' => 20,
                    ),
                ),
            ),
            'output_schema'       => array(
                'type'  => 'array',
                'items' => array(
                    'type'       => 'object',
                    'properties' => array(
                        'id'    => array( 'type' => 'integer' ),
                        'title' => array( 'type' => 'string' ),
                    ),
                    'required'   => array( 'id', 'title' ),
                ),
            ),
            'permission_callback' => function () {
                return current_user_can( 'edit_posts' );
            },
            'execute_callback' => function ( array $input ) {
                $query = new WP_Query(
                    array(
                        'post_type'      => 'post',
                        'post_status'    => 'publish',
                        'posts_per_page' => $input['limit'] ?? 10,
                        'meta_query'     => array(
                            array(
                                'key'     => '_thumbnail_id',
                                'compare' => 'NOT EXISTS',
                            ),
                        ),
                    )
                );

                return array_map(
                    static function ( WP_Post $post ) {
                        return array(
                            'id'    => $post->ID,
                            'title' => get_the_title( $post ),
                        );
                    },
                    $query->posts
                );
            },
            'meta'                => array(
                'show_in_rest' => true,
            ),
        )
    );
} );
PowerShell
curl -u 'editor:application-password' \
  -X POST https://example.com/wp-json/wp-abilities/v1/article-dashboard/list-posts-without-thumbnail/run \
  -H "Content-Type: application/json" \
  -d '{"input":{"limit":5}}'

このコードでは、編集者向けのチェック処理を1つのAbilityとしてまとめています。重要なのは「REST API対応そのもの」より、PHP側の処理と公開のルールがズレにくいことです。

実務では、管理画面の独自パネル、定期点検ツール、外部運用スクリプトの足がかりとしてかなり使いやすそうです。いきなり大規模に入れるより、まずは読み取り系の安全な処理から整理していくと相性がいいと思います。

注意点

  • WordPress 6.9以上が前提
    Developer Handbookでも、Abilities APIはWordPress 6.9以降で利用可能と明記されています。古い案件ではそのまま使えません。
  • 入出力Schemaは手を抜かないほうがいい
    後からREST APIや別チームのコードから触る可能性があるなら、Schemaは面倒でも最初に書いておいたほうが安全です。ここが曖昧だと、結局いつもの独自APIに戻ってしまいます。
  • 権限設計をAbility単位で見直す
    便利だからと何でもshow_in_restにすると危険です。読み取り系でも、誰に見せてよい情報かはAbilityごとに見直したいです。
  • 既存のフックやREST APIを全部置き換える必要はない
    Abilities APIは、新しく整理したい処理に向いた仕組みです。既存実装が安定しているなら、まずは周辺ツール向けの小さな機能から導入するのが現実的です。

まとめ

Abilities APIは、WordPressの機能を“外から見つけやすい形で登録する”ための新しい土台としてかなり筋がいいです。特に、管理用途の小さな処理や、今後ほかの画面や外部ツールから呼ぶかもしれない機能を整理したいときに効きます。

まずは投稿件数取得やチェック系の処理のような、小さくて読み取り中心のAbilityから始めるのがおすすめです。関数を増やすのではなく、機能の単位を揃えていく感覚で触ると、このAPIのよさが見えやすいと思います。

ポイント

  • Abilities APIは、機能名、権限、入出力、実行処理を1か所にまとめて整理できる
  • 管理ダッシュボード補助や点検系ツールのような小さな処理から入れると相性がいい
  • show_in_restを使う前に、Schemaと権限設計をAbility単位で固めるのが重要

参考リンク

read next