リビジョン整理を、人が見ていない間に終わらせる|WP-CLIとAbilities API

← リビジョン削除の全体像 | WordPress プラグイン一覧 | ブログ

最終更新: 2026年9月22日 | 執筆: Takahiro Nishii

結論: リビジョン整理は、WP-CLI を cron に置くのがいちばん確実です。WordPress 6.9 以降であれば、同じ操作を Abilities API の ability としても呼べます。どちらも管理画面を開く必要がありません。ただし SSH が使えない環境では届かない話なので、その場合は画面から実行すれば十分です。
管理画面のボタンには、ひとつだけどうにもならない性質があります。人がそこに座っていないと押せない。リビジョンは毎日静かに増えるのに、掃除は誰かが思い出したときにしか起きません。半年放置して数万件になってから慌てる、というのを私は何度か繰り返しました。

なぜ「ボタン」では足りないのか

リビジョンの蓄積は、記事を更新するたびに全文が複製されるという仕組みから来ています。更新は毎日起きるので、蓄積も毎日進みます。

一方、掃除は人間のイベントです。「そろそろ重いな」と思ったときにしか起きません。この頻度の非対称が、放置されたデータベースの正体です。

掃除の側を機械のイベントにできれば、非対称は消えます。そのために必要なのは、人間のクリック以外の入口です。

WP-CLI:スクリプトと cron のための入口

Revision Autopilot は、管理画面と同じ操作を3つのコマンドとして公開しています。

wp revision-autopilot count
wp revision-autopilot delete --scope=post --limit=100
wp revision-autopilot optimize

まず、触らずに数える

最初に実行すべきは count です。何件あって、どのくらいの容量で、どの投稿タイプに偏っているかを報告するだけで、何も削除しません。

削除の側にも同じ安全装置があります。--dry-run を付けると、該当する対象を報告するだけで一切触れません。

wp revision-autopilot delete --scope=page --dry-run

cron に置く

--all は、何も残らなくなるまで上限付きのバッチを繰り返します。これを週次の cron に置けば、人が見ていなくても片付きます。

# 毎週日曜の午前4時にリビジョンを整理して、テーブルを詰める
0 4 * * 0 cd /path/to/wordpress && \
  wp revision-autopilot delete --all --quiet && \
  wp revision-autopilot optimize --quiet

削除と最適化をこの順に並べているのには理由があります。行を削除してもテーブルのファイルは縮みません。縮むのは OPTIMIZE を実行したときだけです。逆順にすると、最適化した直後に大量の行を消すことになり、空き領域が残ったままになります。

ご注意: 削除したリビジョンは元に戻せません。cron に入れる前に、必ず --dry-run で対象を確認し、データベースのバックアップ体制があることを確かめてください。自動化は「間違いも自動で繰り返す」ということです。

Abilities API:エージェントのための入口

WordPress 6.9 で Abilities API が入りました。ざっくり言えば、プラグインが自分の操作を「ability」という形で登録しておくと、それを外から発見して理解できる仕組みです。

ability は、ただの関数や REST エンドポイントとは違います。ひとつの ability は次を備えています。

  • 名前 — revision-autopilot/count-revisions のような一意な識別子
  • 入力と出力のスキーマ — 何を渡せて、何が返ってくるのかが機械可読な形で書いてある
  • 権限コールバック — 呼び出し側が実行してよいかを、その ability 自身が判断する
  • 振る舞いの注釈 — 読み取り専用なのか、破壊的なのか

この最後の注釈が効きます。REST エンドポイントの一覧を見ても、どれが安全でどれが取り返しのつかない操作かは、URL からは分かりません。ability には readonly / destructive が明示されているので、呼び出す前に区別できます。自動で動くものに操作を渡すとき、この差は小さくありません。

公開されている4つの ability

ability内容種別
count-revisions件数・推定容量・投稿タイプ別の内訳読み取り専用
list-revisions個々のリビジョンを、親投稿と日時つきで1ページぶん読み取り専用
delete-revisions上限付きの1バッチを削除し、残り件数を報告破壊的
optimize-tablesposts と postmeta に OPTIMIZE TABLE破壊的

REST から呼ぶ

読み取り専用の ability は GET、破壊的なものは POST で、次のパスを叩きます。

/wp-json/wp-abilities/v1/abilities/<名前>/run

ここで一度つまずいたので書いておきます。引数を取らない count-revisions と optimize-tables でも、input パラメータは空であっても付ける必要があります。

curl -u user:app-password \
  "https://example.com/wp-json/wp-abilities/v1/abilities/revision-autopilot/count-revisions/run?input="

input を完全に省くと ability_invalid_input が返ります。引数のある方は通常どおり ?input[per_page]=20 のように渡せます。スキーマが「引数なし」なのだから省けるはずだ、と思い込んで15分溶かしました。

入口が増えると、権限の話が変わる

ここが設計上いちばん大事なところです。

管理画面のフォームには nonce があります。「この操作は、いまログインしているこの人が、この画面から意図して送った」ということを担保する仕組みです。ところが WP-CLI にも ability にも、背後にフォームはありません。nonce を検証しようがない。

だから、それぞれの経路が自分で権限を確かめる必要があります。周囲のリクエストから認可を継承してはいけない。Revision Autopilot では、どの ability も、どの CLI コマンドも、実行前に自分で権限を確認します。読み取りには edit_posts、削除と最適化には manage_options が要ります(どちらもフィルタで変更できます)。

権限が足りないとき、素の false ではなくどの権限が足りないかを述べる WP_Error を返すようにしてあります。自動で動くものに拒否を返すなら、理由まで返さないと相手は次の手を選べません。

削除に常に上限があるのも同じ理由です。スコープがどれほど大きくても、1回の呼び出しで1,000件を超えて消すことはありません。結果が残り件数を伝えるので、呼び出し側は意図をもって繰り返すことになります。上限の無い削除は、何かに止められるまで走り続けて、どこまで進んだか分からないまま終わるリクエストになります。

画面・WP-CLI・ability の3経路。無料で公開中です

WordPress.org で無料ダウンロード 機能・安全性の詳細を見る

正直に:この記事が役に立たない人

サーバに SSH で入れないなら、WP-CLI の話は届きません。共用レンタルサーバの多くは WP-CLI を使えますが、管理画面しか触れない契約もあります。その場合は素直に画面から実行してください。ボタンを押す回数が増えるだけで、できることは同じです。

ability も同様で、WordPress 6.9 以降が必要です。それより古い環境では ability が登録されないだけで、エラーにはなりません。画面と WP-CLI はまったく同じように動きます。

自動化は目的ではなく手段です。月に一度ボタンを押して済むサイトなら、手順どおり画面から消すのがいちばん確実です。

よくある質問

cron に入れるのは危なくないですか?

削除は元に戻せないので、慎重さは必要です。ただし対象は post_type = revision に限定され、削除の前に候補はすべて wp_is_post_revision() で確認されます。公開中のコンテンツに触れることはありません。導入前に --dry-run で対象を確かめ、バックアップ体制を確認してください。

WP-Cron でも同じことができますか?

このプラグイン自体はスケジュール機能を持たないので、WP-Cron のイベント登録は自分で書く必要があります。サイトへのアクセスを起点に動く WP-Cron より、OS の cron から wp コマンドを叩くほうが、実行時刻が読めて確実です。

ability は REST API と何が違うのですか?

ability は REST 経由で呼べますが、単なるエンドポイントではありません。入力と出力のスキーマ、権限コールバック、読み取り専用か破壊的かの注釈がセットになっています。呼び出す側は、事前に「何を渡せて」「何が返り」「実行してよいか」「取り返しがつくか」を機械的に確かめられます。

削除が途中で止まったらどうなりますか?

すでに削除されたぶんはそのまま残り、失われるものはありません。サーバは毎バッチでスコープを数え直すので、もう一度実行すれば続きから進みます。同じリビジョンが二重に削除されることはありません。