- WordPressプラグインは自分で作れる
- 作業全体の流れ
- 手順1:目的、機能、プラグイン名を決める
- 手順2:開発に必要なソフトウェアを導入する
- 手順3:wp-envでローカルWordPressを起動する
- 手順4:フォルダー構成を作る
- 手順5:メインPHPファイルとプラグインヘッダーを書く
- 手順6:設定画面を実装する
- 手順7:ショートコードとCSSを実装する
- 手順8:アンインストール処理を追加する
- 手順9:ローカルWordPressで動かす
- コーディングで特に気を付ける点
- 手順10:readme.txtを作る
- 手順11:公開前の品質検査を行う
- 手順12:配布用ZIPを作る
- 手順13:WordPress.orgへ申請する
- 手順14:承認後にSVNへ登録して公開する
- 手順15:公開後の表示と更新を確認する
- よくある失敗
- まとめ
- 参考にしたWordPress公式情報
WordPressプラグインは自分で作れる
WordPressに少し機能を追加したいとき、既存のプラグインを探すだけでなく、自分で小さなプラグインを作る方法があります。プラグインとして実装すれば、WordPress本体やテーマを直接編集せずに機能を追加でき、テーマを変更しても機能を維持しやすくなります。
この記事では、ローカル開発環境の用意から、簡単なプラグインの実装、セキュリティと品質の確認、WordPress.org Plugin Directoryへの申請、承認後のSVN公開までを順番に説明します。
完成させるサンプルは「Simple Notice Box」です。管理画面で案内文を保存し、投稿や固定ページに [simple_notice_box] と入力すると、案内ボックスを表示します。小規模ですが、次の基本要素を一通り含みます。
- プラグインヘッダー
- WordPressのアクションフックとショートコード
- 設定画面とSettings API
- 権限確認とnonce
- 入力の無害化と出力エスケープ
- CSSの正しい読み込み
- アンインストール時のデータ削除
- 国際化に配慮した文字列
- WordPress.org向けの
readme.txt
記事中のバージョン番号や最低動作環境は学習用の例です。実際に公開するときは、自分が検証したWordPressとPHPのバージョンに合わせてください。
作業全体の流れ
作業は次の順番で進めます。
- プラグインの目的と名前を決める
- Docker Desktop、Node.js、コードエディター、SVNを準備する
wp-envでローカルWordPressを起動する- プラグインのフォルダーとメインPHPファイルを作る
- プラグインヘッダーを書く
- 設定画面、ショートコード、CSSを実装する
- アンインストール処理と
readme.txtを追加する - 動作、セキュリティ、互換性を検査する
- 配布用ZIPを作り、WordPress.orgへ申請する
- 承認後、SVNへ正式版を登録して公開する
最初から本番サイトで開発しないことが重要です。PHPの構文エラーや処理ミスがあると、管理画面を含めてサイトが正常に表示できなくなる場合があります。開発と検証はローカル環境で行い、バックアップのある検証サイトを経て本番へ進めます。
手順1:目的、機能、プラグイン名を決める
コードを書く前に「誰の、どの作業を、どう改善するのか」を一文で定義します。今回の例は次のとおりです。
サイト管理者が登録した短い案内文を、投稿や固定ページの任意の位置に同じデザインで表示する。
初回リリースでは機能を絞ります。
- 管理画面で案内文を1つ保存できる
- ショートコードで案内ボックスを表示できる
- 表示用CSSをプラグインから読み込む
- 削除時に保存データを消去する
メール送信、外部API連携、アクセス解析、複数デザインなどは追加しません。機能が増えるほど、権限、個人情報、通信先、エラー処理、保守範囲も増えるためです。
名前とスラッグを決める
表示名をSimple Notice Box、スラッグをsimple-notice-boxとします。スラッグはフォルダー名、メインPHPファイル名、Text Domain、関数接頭辞などの基準になります。
WordPress.orgへ公開する場合は、申請前にディレクトリで類似名を検索し、商標や既存製品と誤認されない固有の名前を選びます。「WordPress」を製品名の先頭に使うなど、公式製品と誤解される命名も避けます。審査で最終的に別のスラッグが指定される可能性もあるため、公開直前まで名前の整合性を確認してください。
手順2:開発に必要なソフトウェアを導入する
この記事では、WordPress公式プロジェクトが提供する@wordpress/env、通称wp-envを使用します。Dockerコンテナ上にWordPressを用意できるため、PCへWebサーバー、PHP、MySQLを個別に設定する手間を減らせます。
必要なソフトウェア
- Docker Desktop:WordPressとデータベースをコンテナで動かす
- Node.jsのLTS版:
npmとnpxを使う - コードエディター:Visual Studio Codeなど
- Git:開発履歴を残す。WordPress.orgへの公開自体はSVNを使う
- Subversion(SVN)クライアント:承認後にWordPress.orgへリリースする
- ZIPを作成・展開できる機能:申請用パッケージを作る
Docker DesktopとNode.jsは、それぞれの公式配布元から入手します。インストール後、ターミナルで次のコマンドが実行できることを確認します。
docker --version
node --version
npm --version
git --version
svn --version
WindowsではPowerShell、macOSやLinuxでは標準のターミナルを利用できます。コマンド例は環境によりパス表記が異なりますが、作るファイルの内容は共通です。
開発用フォルダーを作る
任意の作業場所に、プラグイン用フォルダーを作成します。
mkdir simple-notice-box
cd simple-notice-box
git init
npm init -y
npm install --save-dev @wordpress/env
@wordpress/envをプロジェクト単位でインストールすると、他の案件とバージョンを分離し、npx wp-envで実行できます。チーム開発ではpackage.jsonとロックファイルをGitへ登録し、同じ依存関係を再現できるようにします。
認証情報、.env、データベースの書き出し、個人情報を含むテストデータはGitへ登録しません。
手順3:wp-envでローカルWordPressを起動する
プラグインのルートに.wp-env.jsonを作り、現在のフォルダーをプラグインとして読み込ませます。
{
"$schema": "https://schemas.wp.org/trunk/wp-env.json",
"plugins": ["."],
"config": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true,
"SCRIPT_DEBUG": true
}
}
次のコマンドで起動します。
npx wp-env start
標準設定では、開発サイトはhttp://localhost:8888、テストサイトはhttp://localhost:8889で起動します。画面に表示された管理者情報でログインしてください。ポートが競合するときは、公式ドキュメントにある--auto-portも利用できます。
npx wp-env start --auto-port
作業を止めるときはnpx wp-env stop、状態を確認するときはnpx wp-env statusを使います。resetやdestroyはローカルデータを失う操作なので、必要なデータがないことを確認してから実行します。
WP_DEBUG_LOGには入力値や外部サービスの応答などが残る可能性があります。この設定はローカル開発用です。本番環境で無条件に有効化したり、ログを公開領域へ放置したりしないでください。
手順4:フォルダー構成を作る
最終的に次の構成にします。
simple-notice-box/
├─ assets/
│ └─ css/
│ └─ simple-notice-box.css
├─ languages/
├─ .wp-env.json
├─ package.json
├─ readme.txt
├─ simple-notice-box.php
└─ uninstall.php
WordPress.orgへ提出するZIPには、実行に必要なassets/css、メインPHP、languages、readme.txt、uninstall.phpを含めます。一方、開発専用の.git、.wp-env.json、node_modules、テスト結果、OSの一時ファイル、秘密情報は除外します。
JavaScriptのビルド工程がない今回のプラグインでは、公開ZIPにpackage.jsonを含める必要はありません。ビルド済みJavaScriptを配布する場合は、WordPress.orgの人が人間可読なソースを確認できるよう、ソースの同梱または公開場所とビルド手順の明記が必要です。
手順5:メインPHPファイルとプラグインヘッダーを書く
simple-notice-box.phpを作成します。まず、WordPressがプラグインとして認識するためのヘッダーを書きます。
<?php
/**
* Plugin Name: Simple Notice Box
* Plugin URI: https://example.com/simple-notice-box/
* Description: 保存した案内文をショートコードで表示します。
* Version: 1.0.0
* Requires at least: 6.6
* Requires PHP: 7.4
* Author: Your Name
* Author URI: https://example.com/
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: simple-notice-box
* Domain Path: /languages
*
* @package SimpleNoticeBox
*/
defined( 'ABSPATH' ) || exit;
example.comとYour Nameは自分の情報へ置き換えます。最低動作バージョンは、単に古い数字を書くのではなく、実際にテストした範囲から決めます。
プラグインヘッダーで押さえるべき作法
公式仕様上、必須なのはPlugin Nameですが、公開・保守するプラグインでは関連項目も適切に記述します。ヘッダーを持つファイルは、プラグイン内でメインPHPファイル1つだけにします。
Plugin Name:管理画面に表示される名前。既存製品や公式機能と誤認されない名前にするPlugin URI:プラグイン固有の紹介・文書ページ。WordPress.orgのURLは指定せず、別製品と同じURLを使い回さないDescription:管理画面用の短い説明。公式ガイドでは140文字未満が推奨されているVersion:プラグイン自身のバージョン。リリースごとに増やし、readme.txtのStable tagと一致させるRequires at least:動作を保証する最低WordPressバージョン。メインPHPの値がディレクトリで参照されるRequires PHP:動作を保証する最低PHPバージョン。使用する構文や依存ライブラリと合わせるAuthor、Author URI:開発者名と開発者ページ。権利者と連絡先の運用を決めておくLicense、License URI:WordPress.orgではGPL互換ライセンスが必要。コードだけでなく同梱画像・フォント・ライブラリも確認するText Domain:翻訳対象を識別する文字列。WordPress.org公開時は原則としてプラグインスラッグと一致させるDomain Path:翻訳ファイルを置く相対パス。通常は/languagesNetwork:マルチサイトのネットワーク有効化だけを認める場合にtrueを指定する。不要なら書かないRequires Plugins:依存するWordPress.orgプラグインのスラッグをカンマ区切りで指定する。ファイルパスは書かないUpdate URI:WordPress.org外で配布するプラグインが、同名プラグインの更新で誤って上書きされるのを避けるための項目。WordPress.orgへ公開する今回の例では省略する
Versionを1.02のように表現すると、PHPのversion_compare()で意図と異なる比較になることがあります。1.0.0、1.1.0、2.0.0のように、チーム内で一貫した規則を使います。
直接アクセスを防ぐ
ヘッダー直後の次の行は、PHPファイルがWordPressを経由せず直接呼び出された場合に処理を終了します。
defined( 'ABSPATH' ) || exit;
これだけでプラグイン全体が安全になるわけではありません。権限、nonce、入力処理、出力処理は、それぞれの処理箇所で必要です。
手順6:設定画面を実装する
先ほどのdefined()の下へ、次のコードを追加します。すべての関数名にsimple_notice_box_という固有の接頭辞を付け、他のテーマやプラグインとの名前衝突を防ぎます。
/**
* 設定を登録する。
*/
function simple_notice_box_register_setting() {
register_setting(
'simple_notice_box_settings',
'simple_notice_box_message',
array(
'type' => 'string',
'sanitize_callback' => 'simple_notice_box_sanitize_message',
'default' => '',
)
);
add_settings_section(
'simple_notice_box_main_section',
__( '案内文の設定', 'simple-notice-box' ),
'__return_false',
'simple-notice-box'
);
add_settings_field(
'simple_notice_box_message',
__( '案内文', 'simple-notice-box' ),
'simple_notice_box_render_message_field',
'simple-notice-box',
'simple_notice_box_main_section'
);
}
add_action( 'admin_init', 'simple_notice_box_register_setting' );
/**
* 案内文を保存前に無害化する。
*
* @param mixed $value 入力値。
* @return string
*/
function simple_notice_box_sanitize_message( $value ) {
if ( ! is_string( $value ) ) {
return '';
}
return sanitize_textarea_field( $value );
}
/**
* 設定メニューを追加する。
*/
function simple_notice_box_add_options_page() {
add_options_page(
__( 'Simple Notice Box', 'simple-notice-box' ),
__( 'Notice Box', 'simple-notice-box' ),
'manage_options',
'simple-notice-box',
'simple_notice_box_render_options_page'
);
}
add_action( 'admin_menu', 'simple_notice_box_add_options_page' );
/**
* 入力欄を表示する。
*/
function simple_notice_box_render_message_field() {
$message = get_option( 'simple_notice_box_message', '' );
?>
<textarea
id="simple_notice_box_message"
name="simple_notice_box_message"
rows="5"
class="large-text"
><?php echo esc_textarea( $message ); ?></textarea>
<p class="description">
<?php esc_html_e( '投稿内で [simple_notice_box] を入力すると表示されます。', 'simple-notice-box' ); ?>
</p>
<?php
}
/**
* 設定画面を表示する。
*/
function simple_notice_box_render_options_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php esc_html_e( 'Simple Notice Box', 'simple-notice-box' ); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields( 'simple_notice_box_settings' );
do_settings_sections( 'simple-notice-box' );
submit_button();
?>
</form>
</div>
<?php
}
コード例の<h1>はWordPress管理画面内のページタイトルであり、この記事本文の見出しではありません。記事本文はH2から構成しています。
Settings APIを使う理由
register_setting()、settings_fields()、do_settings_sections()などのSettings APIを使うと、WordPress標準の設定保存フローを利用できます。settings_fields()は必要なnonceフィールド等を出力します。
ただし、nonceは「その操作を意図して実行した可能性」を検証する仕組みであり、権限そのものではありません。そのため画面表示ではcurrent_user_can( 'manage_options' )を確認し、メニュー登録でも同じ権限を指定しています。
入力時に行う処理
$_POSTなどの外部入力をそのまま保存しません。今回の案内文はHTMLを許可しない複数行テキストなので、sanitize_textarea_field()を使います。
入力の仕様が決まっている場合は、可能なら無害化だけでなく検証を優先します。例えば整数ならabsint()、メールアドレスならis_email()とsanitize_email()、許可値が決まる選択肢なら配列との厳密比較を行います。万能な関数を1つ通すのではなく、データの意味に合う処理を選びます。
手順7:ショートコードとCSSを実装する
同じPHPファイルへ次のコードを追加します。
/**
* フロントエンド用CSSを読み込む。
*/
function simple_notice_box_enqueue_styles() {
wp_enqueue_style(
'simple-notice-box',
plugin_dir_url( __FILE__ ) . 'assets/css/simple-notice-box.css',
array(),
'1.0.0'
);
}
add_action( 'wp_enqueue_scripts', 'simple_notice_box_enqueue_styles' );
/**
* 案内ボックスのショートコードを出力する。
*
* @return string
*/
function simple_notice_box_render_shortcode() {
$message = get_option( 'simple_notice_box_message', '' );
if ( '' === $message ) {
return '';
}
return sprintf(
'<aside class="simple-notice-box" role="note">%s</aside>',
nl2br( esc_html( $message ) )
);
}
add_shortcode( 'simple_notice_box', 'simple_notice_box_render_shortcode' );
assets/css/simple-notice-box.cssを作ります。
.simple-notice-box {
margin-block: 1.5rem;
padding: 1rem 1.25rem;
border-inline-start: 4px solid #2271b1;
background: #f0f6fc;
color: #1e1e1e;
line-height: 1.7;
}
出力時にエスケープする
保存時に無害化した値でも、データベース内の値を無条件に信用しません。HTML本文として出す文字列はesc_html()、属性値はesc_attr()、URLはesc_url()、テキストエリアはesc_textarea()のように、出力先の文脈に合う関数を直前で使用します。
今回のnl2br( esc_html( $message ) )は、先にHTML特殊文字をエスケープしてから、改行を<br>へ変換します。順序を逆にすると、自分で加えた<br>まで文字として表示されるため注意してください。
CSSとJavaScriptは正規のAPIで読み込む
CSSやJavaScriptをPHPから直接<link>や<script>として出力せず、wp_enqueue_style()とwp_enqueue_script()を使います。依存関係、読み込み順、重複排除、バージョン指定をWordPressに任せられます。
この小さな例ではCSSを全フロント画面で読み込んでいます。規模が大きくなったら、対象ブロックやショートコードがあるページだけで読み込む設計を検討します。ただし、本文の解析時期とwp_headの実行順を理解せずに条件化すると、CSSが間に合わないことがあります。正しく検証できる方法を選んでください。
手順8:アンインストール処理を追加する
無効化と削除は異なります。無効化は一時停止なので通常は設定を残します。管理画面からプラグインを削除したときだけ、不要な設定を消すにはuninstall.phpを使います。
<?php
/**
* Simple Notice Box uninstall handler.
*
* @package SimpleNoticeBox
*/
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit;
}
delete_option( 'simple_notice_box_message' );
実際の製品で、利用者が再インストールに備えてデータ保持を望む場合は「削除時にデータを残す」設定を用意する方法もあります。マルチサイト、カスタムテーブル、予約イベント、ユーザーメタ、アップロードファイルを使うプラグインでは、それぞれの削除範囲を明確に設計してください。
手順9:ローカルWordPressで動かす
管理画面の「プラグイン」でSimple Notice Boxを有効化します。次に「設定」→「Notice Box」を開き、案内文を保存します。投稿または固定ページへショートコードブロックを追加し、次を入力します。
[simple_notice_box]
プレビューと公開画面で、案内文とデザインを確認します。最低限、次の条件を試してください。
- 未入力なら何も表示されない
- 日本語、英数字、記号、複数行を保存できる
<script>などを入力してもコードとして実行されない- 管理者以外に設定画面が表示されない
- ショートコードを複数置いても表示が崩れない
- テーマを変更しても読める
- スマートフォン幅、拡大表示、キーボード操作で利用できる
- プラグインを無効化しても投稿本文が壊れず、ショートコード文字列だけが残る
- 削除後に
simple_notice_box_messageオプションが消える
エラーがないように見えても、wp-content/debug.logとブラウザーの開発者ツールを確認します。PHP Warning、Deprecated、JavaScriptエラー、404になっているCSSなどを残さないようにします。
コーディングで特に気を付ける点
サンプルを機能追加していくときは、次の原則を崩さないようにします。
WordPress本体を変更しない
wp-adminやwp-includes内のファイルを編集してはいけません。更新時に上書きされるだけでなく、サイトの安全性と再現性を損ないます。機能追加はアクション、フィルター、公開APIを使います。
名前衝突を防ぐ
グローバル関数、定数、クラス、オプション名、スクリプトハンドルには固有の接頭辞を付けます。規模が大きい場合は名前空間とオートローダーも検討します。短すぎるsave_data()のような名前は避けます。
入力、保存、出力を分けて考える
- 検証:許可された値か確認する
- 無害化:保存前に不要・危険な部分を取り除く
- エスケープ:HTML、属性、URL、JavaScriptなど出力先に合わせて直前に安全化する
同じ値に同じ関数を機械的に使うのではなく、データ型と利用場所から判断します。$_GET、$_POST、$_REQUEST、$_FILESを読む場合は、存在確認を行い、必要に応じてwp_unslash()した後、適切に検証・無害化します。
nonceと権限確認を両方行う
設定変更、削除、Ajax、REST APIなど状態を変える処理は、nonceだけで安全とはいえません。current_user_can()で実行権限を確認し、nonceでリクエストの意図を確認します。権限名は「管理者かどうか」ではなく、その操作に必要なCapabilityで判断します。
SQLはWordPress APIを優先する
オプション、投稿、メタデータ、ユーザーなどはWordPress APIを利用します。独自SQLが必要な場合は、テーブル名や値を文字列連結せず、$wpdb->prepare()を使います。テーブル作成、更新、削除、文字コード、インデックス、マルチサイト対応まで設計が必要です。
ファイルパスとURLを混同しない
サーバー内のファイル参照にはplugin_dir_path()、ブラウザーへ渡すURLにはplugin_dir_url()やplugins_url()を使います。WindowsとLinuxの区切り文字を前提にした文字列連結や、wp-contentの場所を固定した実装を避けます。
外部通信と個人情報を最小化する
外部API、解析、トラッキング、広告、ライセンス確認を行う場合は、通信先、送信内容、目的、頻度、同意、停止方法、プライバシー情報を整理します。WordPress.orgのプラグインは、利用者の明確な同意なしに追跡してはいけません。秘密鍵をプラグイン内へ埋め込んでも保護にはなりません。
翻訳可能な文字列にする
画面に表示する固定文字列は、__()、esc_html__()、esc_html_e()などの国際化関数を使い、Text Domainを統一します。変数を含む翻訳文字列は、文全体を翻訳できる形にし、プレースホルダーとtranslator commentを適切に使います。
アクセシビリティを後付けにしない
フォームにはラベルを関連付け、キーボードで操作できる標準要素を使い、色だけで状態を伝えません。管理画面でもフロントエンドでも、WordPressのアクセシビリティコーディング標準を意識します。
バージョンと変更履歴を同期する
メインPHPのVersion、readme.txtのStable tag、リリースタグ、配布ZIPの中身を一致させます。コードのバージョンを上げずに別内容を再公開すると、更新判定や利用者の問題切り分けが困難になります。
手順10:readme.txtを作る
WordPress.orgのプラグインページは、主にreadme.txtの内容から生成されます。通常のREADME.mdではなく、小文字のファイル名readme.txtをプラグイン直下へ置きます。
=== Simple Notice Box ===
Contributors: your-wordpress-org-id
Tags: notice, shortcode, message
Requires at least: 6.6
Tested up to: 6.9
Stable tag: 1.0.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Display a saved notice message anywhere with a shortcode.
== Description ==
Simple Notice Box adds a settings field for one notice message.
Place `[simple_notice_box]` in a post or page to display it.
The plugin does not send data to external services.
== Installation ==
1. Upload the plugin files to `/wp-content/plugins/simple-notice-box/`, or install the plugin ZIP from the Plugins screen.
2. Activate the plugin.
3. Open Settings > Notice Box and save a message.
4. Add `[simple_notice_box]` to a post or page.
== Frequently Asked Questions ==
= Does this plugin send data outside the site? =
No. This sample plugin does not connect to an external service.
== Changelog ==
= 1.0.0 =
* Initial release.
your-wordpress-org-idは表示名やメールアドレスではなく、大文字・小文字を含めて正確なWordPress.orgユーザー名に置き換えます。
Tested up to: 6.9は記入例です。実際に試した最新のメジャーバージョンを記載してください。未検証の最新版を推測で書いてはいけません。説明文、FAQ、変更履歴は宣伝文句を並べる場所ではなく、利用者が機能、制約、導入方法を判断できる内容にします。
WordPress.orgはtrunk/readme.txtのStable tagを読み、そのバージョンのtags/を参照します。Stable tag: trunkは新規プラグインで使用せず、1.0.0のような正式なバージョンを指定します。公式のReadme Validatorで構文を確認してください。
手順11:公開前の品質検査を行う
ZIPを作る前に、機能だけでなく安全性と配布物を検査します。
Plugin Checkを実行する
検証用WordPressの「プラグインを追加」で公式のPlugin Checkをインストールして有効化します。「ツール」→「Plugin Check」でSimple Notice Boxを選び、チェックを実行します。
WP-CLIを使える環境では、Plugin Checkを有効化したうえで次の形式でも実行できます。
wp plugin check simple-notice-box
Plugin Checkは、WordPress.orgの新規申請で使われる多くの検査や、国際化、アクセシビリティ、性能、セキュリティ上の懸念を検出します。ただし自動検査は手動レビューの代わりではありません。警告の理由を確認し、修正または妥当な根拠を記録します。
公開前チェックリスト
- メインPHPのヘッダーは1ファイルだけにある
- プラグイン名、フォルダー名、Text Domain、関数接頭辞が一貫している
- WordPress本体、他プラグイン、テーマのコードを直接変更していない
- すべての入力をデータ型に応じて検証または無害化している
- すべての動的出力を文脈に応じてエスケープしている
- 状態変更処理でCapabilityとnonceを確認している
- SQL、ファイル操作、アップロード、外部通信を安全に扱っている
- PHP Warning、Deprecated、JavaScriptエラーがない
- 有効化、無効化、再有効化、削除、再インストールを試した
- 最低対応環境と最新の検証環境で試した
- 複数テーマ、スマートフォン幅、キーボード操作で確認した
- マルチサイト対応をうたう場合はネットワーク有効化とサイト単位の挙動を確認した
- GPL互換性と、同梱する第三者素材のライセンスを確認した
- minify前のソースとビルド手順を確認できる
readme.txtを公式Validatorで検査した- Plugin Checkの指摘を確認した
- テスト用データ、ログ、ZIP、秘密情報、不要ファイルが配布物にない
手順12:配布用ZIPを作る
申請用ZIPは、展開した直下にスラッグ名のフォルダーが1つある形にします。
simple-notice-box.zip
└─ simple-notice-box/
├─ assets/
├─ languages/
├─ readme.txt
├─ simple-notice-box.php
└─ uninstall.php
node_modules、.git、開発環境設定、テスト用ファイル、別のZIPを含めません。ZIPを一度別の場所へ展開し、クリーンなWordPressの「プラグインを追加」→「プラグインのアップロード」からインストールします。開発フォルダーで動いたことだけでは、配布ZIPの完成確認になりません。
手順13:WordPress.orgへ申請する
申請にはWordPress.orgアカウントと、受信確認できるメールアドレスが必要です。会社名義で公開する場合は、継続して管理できる会社のメールアドレスを使うことが公式に案内されています。plugins@wordpress.orgからのメールを受信できるようにします。
申請前に次を確認します。
- Detailed Plugin Guidelinesを全文確認する
- 希望する名前とスラッグの類似・商標問題を確認する
- 完成したプラグインをZIPから新規インストールして試す
- Plugin CheckとReadme Validatorを通す
- 外部通信、トラッキング、アップセル、同梱ライブラリの扱いを確認する
- WordPress.orgのプラグイン追加ページへログインする
- 完成したZIPと、機能を簡潔に説明する情報を提出する
提出後は自動検査と手動レビューが行われます。審査時間は一定ではありません。公式の申請ページには通常1〜10日、5営業日以内を目標とする案内がある一方、別のハンドブックには14営業日以内という記述もあります。混雑やプラグインの複雑さで変わるため、公開日を確約せず余裕を持って申請します。
審査担当からメールが届いたら、指摘ごとに原因、修正内容、再検査結果を整理して返信します。指摘箇所だけを場当たり的に直すのではなく、同じ問題が他のファイルにもないか横断的に確認します。
審査承認だけでは、まだプラグインページに完成版が公開されません。承認メールで発行されたSVNリポジトリへ、開発者がリリースファイルを登録する必要があります。
手順14:承認後にSVNへ登録して公開する
WordPress.orgのSVNは日々の開発履歴を置く場所ではなく、利用者へ配布する完成版のリリースリポジトリとして扱います。開発はGit等で行い、検査済みのファイルだけをSVNへ反映します。
承認されたスラッグがsimple-notice-boxだった場合、作業用フォルダーへチェックアウトします。
svn checkout https://plugins.svn.wordpress.org/simple-notice-box simple-notice-box-svn
cd simple-notice-box-svn
基本構成は次の3つです。
trunk/:現在の開発・配布候補コードtags/:バージョンごとの正式リリースassets/:WordPress.orgページ用のアイコン、バナー、スクリーンショット
プラグイン本体のファイルをtrunk/へ直接配置します。trunk/simple-notice-box/simple-notice-box.phpのように、プラグインフォルダーをもう一段作ってはいけません。
simple-notice-box-svn/
├─ assets/
├─ tags/
└─ trunk/
├─ assets/css/simple-notice-box.css
├─ languages/
├─ readme.txt
├─ simple-notice-box.php
└─ uninstall.php
新規ファイルをSVNの管理対象へ追加し、差分を確認します。
svn add trunk/* --force
svn status
svn diff
次に、正式版1.0.0のタグをSVNのコピー操作で作ります。
svn copy trunk tags/1.0.0
svn status
svn diff
この時点で、メインPHPのVersion: 1.0.0、trunk/readme.txtとtags/1.0.0/readme.txtのStable tag: 1.0.0が一致していることを再確認します。
WordPress.org用の画像は、プラグイン本体のtrunk/assetsではなく、SVNルートのassets/へ置きます。アイコンやバナーのファイル名・サイズは公式のPlugin Assets仕様に従います。
準備ができたらコミットします。
svn commit -m "Release version 1.0.0"
必要な場合は、WordPress.orgのユーザー名とSVN用パスワードを使用します。パスワードをコマンド履歴、スクリプト、Git、記事、画面共有へ残さないでください。
SVNへコミットすると公開処理が始まります。準備不足のコードを試しに送る場所ではなく、公開してよい完成物だけを登録します。SVNへZIPファイルを置く必要もありません。
手順15:公開後の表示と更新を確認する
初回コミット後、WordPress.orgのプラグインページで次を確認します。
- プラグイン名、説明、バージョン、作者リンク
- ダウンロードと新規インストール
readme.txtから生成された説明、FAQ、変更履歴- アイコン、バナー、スクリーンショット
- 最低WordPress・PHPバージョンと検証済みバージョン
- サポートフォーラム、翻訳ページ
- クリーンな環境での有効化と基本機能
公開後は終わりではありません。WordPress、PHP、ブラウザーの更新、脆弱性報告、サポート問い合わせへ継続対応します。脆弱性が疑われる場合は公開フォーラムへ再現手順を詳しく書く前に、WordPress.orgの案内と適切な責任ある開示手順を確認します。
更新版では、Git上で開発と検査を終えた後、SVNをsvn updateし、trunkを更新します。メインPHPのVersionとreadme.txtのStable tagを新しい番号に合わせ、svn copy trunk tags/新バージョンでタグを作ってからコミットします。SVNには細かな開発途中の変更を連続して送らず、完成したリリース単位で反映します。
よくある失敗
本番サイトのテーマファイルへ直接書く
テーマ更新で消え、テーマ変更にも追従できません。機能はプラグインへ分離し、ローカル環境で開発します。
Plugin Nameだけ書いて公開準備を終える
WordPressは認識しても、利用者とディレクトリに必要な互換性、ライセンス、バージョン、翻訳情報が不足します。各ヘッダーの意味を理解して記入します。
保存時のsanitizeだけで安心する
保存後のデータや外部APIの応答も信頼せず、表示箇所で文脈に合ったエスケープを行います。
nonceを権限確認の代わりに使う
nonceは認証・認可の代替ではありません。Capability確認と組み合わせます。
readmeのStable tagとPHPのVersionが違う
WordPress.orgが参照するリリースと表示バージョンがずれ、正しい更新を配布できない原因になります。
SVNへプラグインZIPや開発途中のファイルを入れる
SVNにはリリース対象の個別ファイルだけを置きます。秘密情報、ログ、開発依存、不要なZIPを含めません。
承認されたら自動公開されると思う
承認後に発行されるSVNへ、自分でtrunkと正式タグをコミットして初めて公開へ進みます。
まとめ
WordPressプラグインは、メインPHPファイルとヘッダーだけでも認識させられます。しかし、第三者が安心して使える形で公開するには、目的の限定、再現可能な開発環境、WordPress APIに沿った実装、入力と出力の安全対策、ライセンス、互換性テスト、readme、審査対応、SVNによるリリースまでが必要です。
今回のサンプルを順番に作れば、設定画面で保存した案内文をショートコードで表示する小さなプラグインが完成します。次の段階では、設定項目を増やす前に、自動テスト、コーディング規約検査、翻訳ファイル生成、継続的インテグレーションを追加すると、保守しやすい開発へ発展させられます。
プラグインの要件整理、Gutenberg対応、セキュリティ検査、WordPress.org審査・公開まで一貫した支援が必要な場合は、WordPressプラグイン開発の相談窓口をご利用ください。

参考にしたWordPress公式情報
以下は2026年9月7日に確認しました。公開手順やガイドラインは更新されるため、実際の申請時に最新版を再確認してください。

