Contents
1. WordPress プラグインとは何か(基本構造)
1‑1. 結論
WordPress のプラグインは、「WordPress 本体に機能を付加する」小さな PHP パッケージです。
最小構成は次の2点だけで動作します。
| 必要項目 | 内容 |
|---|---|
| 必須ヘッダー | Plugin Name、Version、Author などを記述したコメントブロック |
| 配置ディレクトリ | wp-content/plugins/プラグイン名/ 配下に PHP ファイルを置く |
1‑2. 背景(なぜヘッダーとフォルダだけで動くのか)
WordPress は起動時に wp-content/plugins/ 以下のすべてのディレクトリを走査し、「プラグインヘッダー」 が見つかった PHP ファイルを自動的に読み込みます。
この仕組みは フックシステム(アクションとフィルター) と連携しており、テーマやコアコードを書き換えることなく機能追加が可能です。
1‑3. 最小構成サンプル
|
1 2 3 4 5 6 7 |
my-first-plugin/ ├─ my-first-plugin.php ← エントリーポイント(必須ヘッダーあり) ├─ assets/ ← CSS・画像などの静的ファイル │ ├─ style.css │ └─ icon.svg └─ readme.txt ← WordPress.org 用説明文 |
1‑3‑1. my-first-plugin.php のヘッダー例(PHP 8.2 対応)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php /** * Plugin Name: My First Plugin * Description: カスタムショートコードと管理画面メニューを提供する超初心者向けプラグイン * Version: 1.0.0 * Author: Your Name * Requires at least: 6.4 * Tested up to: 6.5 * Requires PHP: 8.2 * License: GPLv2 or later * Text Domain: my-first-plugin */ |
ポイント
-Plugin Nameが必須です。
-Text Domainは i18n 対応時に使用します。
- 行頭の空白や全角文字は混在させないようにしましょう(表記揺れ防止)。
1‑4. まとめ
- ヘッダー と ディレクトリ構造 が整っていればプラグインは即座に有効化可能。
- 後はフック(
add_action/add_filter)や独自クラスを組み込んで機能拡張していきます。
2. ローカル開発環境の構築
2‑1. 結論
MAMP(macOS)/XAMPP(Windows) + WP‑CLI の組み合わせなら、数分で PHP 8.2 対応 の WordPress 環境が完成します。
2‑2. 背景
- ローカルサーバーは PHP バージョン・データベース設定を自由に変更できるため、本番環境と同等のテストが可能です。
- WP‑CLI はコマンド一発で WordPress 本体、プラグイン、テーマのダウンロード・インストール・アップデートが行えるので、手作業によるミスを防げます。
2‑3. 手順詳細
2‑3‑1. MAMP / XAMPP のインストール
| OS | 推奨パッケージ |
|---|---|
| macOS | MAMP(公式サイトから最新版ダウンロード) |
| Windows | XAMPP(公式サイトから最新版ダウンロード) |
ポイント
- インストール時は「PHP 8.2」またはそれ以上を選択してください。
- 起動後、http://localhost/phpmyadmin/にアクセスし、データベースwp_local(文字コードは utf8mb4)を作成します。
2‑3‑2. WP‑CLI の導入
|
1 2 3 4 5 |
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar php wp-cli.phar --info # 正常に情報が表示されれば OK chmod +x wp-cli.phar sudo mv wp-cli.phar /usr/local/bin/wp |
ヒント
- macOS の場合はbrew install wp-cliでもインストール可能です。
2‑3‑3. コマンドで WordPress セットアップ
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# プロジェクトディレクトリ作成 mkdir ~/Sites/my-site && cd $_ # WordPress 本体を日本語版でダウンロード wp core download --locale=ja # wp-config.php を自動生成(DB情報は先ほど作成したもの) wp config create \ --dbname=wp_local \ --dbuser=root \ --dbpass=root \ --dbhost=localhost \ --skip-check # データベース作成 wp db create # サイトインストール wp core install \ --url="http://localhost/my-site" \ --title="My Local WP" \ --admin_user=admin \ --admin_password=Pass123! \ --admin_email=admin@example.com |
結果
-http://localhost/my-siteにアクセスすると、WordPress のトップページが表示されます。
2‑4. デバッグ環境の有効化
|
1 2 3 4 5 |
// wp-config.php の末尾に追記 define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); // /wp-content/debug.log に出力 define( 'WP_DEBUG_DISPLAY', false ); // 画面表示は抑制 |
2‑5. まとめ
- MAMP/XAMPP + WP‑CLI は初心者でも安全・高速に開発環境を構築できる最適解です。
wpコマンドでプラグインの有効化や更新も簡単に行えるので、作業が格段に楽になります。
3. PHP 基礎と WordPress への応用例
3‑1. 結論
PHP 8.2 の基本文法(変数・配列・関数)を押さえたうえで、名前空間 + オートローディング を導入すれば、プラグインコードは モジュール化・保守性向上 が期待できます。
3‑2. 背景
- WordPress 本体は手続き型関数が中心ですが、近年の開発トレンドでは クラスベース + 名前空間 の利用が推奨されています。
- オートローディングにより
require/includeを自動化でき、ファイル構成が増えても管理が楽になります。
3‑3. 実装サンプル
3‑3‑1. エントリーポイント(my-first-plugin.php)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php /** * Plugin Name: My First Plugin * Description: カスタムショートコードと管理画面メニューを提供するプラグイン * Version: 1.0.0 * Author: Your Name * Requires PHP: 8.2 * Text Domain: my-first-plugin */ if ( ! defined( 'ABSPATH' ) ) { exit; // 直接アクセス防止 } // 名前空間とオートローダーの登録 require_once __DIR__ . '/src/autoload.php'; // フックはクラス側で定義するのでここでは何もしない |
3‑3‑2. オートローダー(src/autoload.php)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php declare( strict_types=1 ); spl_autoload_register( function ( string $class ): void { // プラグイン固有のプレフィックス $prefix = 'MyFirstPlugin\\'; $base_dir = __DIR__ . '/'; // プレフィックスが一致しなければ何もしない if ( 0 !== strpos( $class, $prefix ) ) { return; } // クラス名からファイルパスへ変換 $relative_class = substr( $class, strlen( $prefix ) ); $file = $base_dir . str_replace( '\\', '/', $relative_class ) . '.php'; if ( file_exists( $file ) ) { require $file; } } ); |
3‑3‑3. ショートコードクラス(src/Shortcode.php)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php declare( strict_types=1 ); namespace MyFirstPlugin; final class Shortcode { /** * init フックで登録するメソッド */ public static function register(): void { add_shortcode( 'hello_world', [ self::class, 'render' ] ); } /** * ショートコード本体 * * @param array $atts 属性(例: name="WordPress") * @return string HTML 出力 */ public static function render( array $atts = [] ): string { $defaults = [ 'name' => 'World' ]; $args = shortcode_atts( $defaults, $atts, 'hello_world' ); $name = sanitize_text_field( $args['name'] ); return sprintf( '<p>Hello, %s!</p>', esc_html( $name ) ); } } // フック登録(init 時にショートコードを追加) add_action( 'init', [ Shortcode::class, 'register' ] ); |
3‑3‑4. 管理画面クラス(src/AdminPage.php)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php declare( strict_types=1 ); namespace MyFirstPlugin; final class AdminPage { public static function init(): void { add_action( 'admin_menu', [ self::class, 'add_menu' ] ); add_action( 'admin_post_mfp_save', [ self::class, 'save_options' ] ); } /** 管理メニューの追加 */ public static function add_menu(): void { add_menu_page( __( 'My First Plugin Settings', 'my-first-plugin' ), __( 'First Plugin', 'my-first-plugin' ), 'manage_options', 'my-first-plugin', [ self::class, 'render_page' ], 'dashicons-admin-generic' ); } /** 設定ページの表示 */ public static function render_page(): void { $greeting = get_option( 'mfp_greeting', '' ); ?> <div class="wrap"> <h1><?php esc_html_e( 'My First Plugin Settings', 'my-first-plugin' ); ?></h1> <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"> <?php wp_nonce_field( 'mfp_form', 'mfp_nonce' ); ?> <input type="hidden" name="action" value="mfp_save"> <table class="form-table"> <tr> <th scope="row"><label for="greeting"><?php esc_html_e( 'Greeting Text', 'my-first-plugin' ); ?></label></th> <td><input type="text" id="greeting" name="greeting" value="<?php echo esc_attr( $greeting ); ?>" class="regular-text"></td> </tr> </table> <?php submit_button(); ?> </form> </div> <?php } /** オプション保存処理 */ public static function save_options(): void { if ( ! isset( $_POST['mfp_nonce'] ) || ! wp_verify_nonce( $_POST['mfp_nonce'], 'mfp_form' ) ) { wp_die( __( 'Nonce verification failed.', 'my-first-plugin' ) ); } $greeting = sanitize_text_field( $_POST['greeting'] ?? '' ); update_option( 'mfp_greeting', $greeting ); // 保存後は設定ページにリダイレクト wp_redirect( admin_url( 'admin.php?page=my-first-plugin&status=updated' ) ); exit; } } // 初期化フックでクラスを有効化 AdminPage::init(); |
3‑4. まとめ
- PHP 基礎(型宣言・strict モード)と 名前空間 + オートローディング を組み合わせると、プラグインは 自己完結型のモジュール になります。
- クラスごとに責務を分割すれば、将来的な機能追加やバグ修正が容易です。
4. 最初のシンプルプラグイン作成手順(実践編)
4‑1. 結論
my-first-plugin.php にヘッダーを書き、ショートコード と 管理画面メニュー を add_action/add_shortcode で登録すれば、数分で動くプラグインが完成します。
4‑2. 実装フロー
| 手順 | 内容 |
|---|---|
| ① ファイル作成 | wp-content/plugins/my-first-plugin/ 配下に my-first-plugin.php を置く |
| ② ヘッダー記述 | 前節のヘッダー例をコピー(必須項目はすべて埋める) |
| ③ ショートコード実装 | add_shortcode( 'hello_world', … ) で簡易的な出力を作成 |
| ④ 管理画面メニュー実装 | add_menu_page() とフォーム処理(nonce・サニタイズ)を追加 |
| ⑤ デバッグ設定 | WP_DEBUG を有効化し、エラーログで確認 |
4‑2‑1. 完全コード例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
<?php /** * Plugin Name: My First Plugin * Description: カスタムショートコードと管理画面メニューを提供するプラグイン * Version: 1.0.0 * Author: Your Name * Requires PHP: 8.2 * Text Domain: my-first-plugin */ if ( ! defined( 'ABSPATH' ) ) { exit; // 直接アクセス防止 } /* ------------------------------------------------- * ショートコード実装 * ------------------------------------------------- */ function mfp_hello_world_shortcode( $atts ) { $atts = shortcode_atts( [ 'name' => 'World' ], $atts, 'hello_world' ); $name = sanitize_text_field( $atts['name'] ); return '<p>Hello, ' . esc_html( $name ) . '!</p>'; } add_action( 'init', function() { add_shortcode( 'hello_world', 'mfp_hello_world_shortcode' ); } ); /* ------------------------------------------------- * 管理画面メニュー実装 * ------------------------------------------------- */ function mfp_add_admin_page() { add_menu_page( __( 'My First Plugin Settings', 'my-first-plugin' ), __( 'First Plugin', 'my-first-plugin' ), 'manage_options', 'my-first-plugin', 'mfp_render_admin_page', 'dashicons-admin-generic' ); } add_action( 'admin_menu', 'mfp_add_admin_page' ); function mfp_render_admin_page() { // 保存済みオプション取得 $greeting = get_option( 'mfp_greeting', '' ); ?> <div class="wrap"> <h1><?php esc_html_e( 'My First Plugin Settings', 'my-first-plugin' ); ?></h1> <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"> <?php wp_nonce_field( 'mfp_form', 'mfp_nonce' ); ?> <input type="hidden" name="action" value="mfp_save"> <table class="form-table"> <tr> <th scope="row"><label for="greeting"><?php esc_html_e( 'Greeting Text', 'my-first-plugin' ); ?></label></th> <td><input type="text" id="greeting" name="greeting" value="<?php echo esc_attr( $greeting ); ?>" class="regular-text"></td> </tr> </table> <?php submit_button(); ?> </form> </div> <?php } /* ------------------------------------------------- * 設定保存処理(admin_post フック) * ------------------------------------------------- */ function mfp_save_options() { if ( ! isset( $_POST['mfp_nonce'] ) || ! wp_verify_nonce( $_POST['mfp_nonce'], 'mfp_form' ) ) { wp_die( __( 'Nonce verification failed.', 'my-first-plugin' ) ); } $greeting = sanitize_text_field( $_POST['greeting'] ?? '' ); update_option( 'mfp_greeting', $greeting ); // 保存後は設定ページへリダイレクト wp_redirect( admin_url( 'admin.php?page=my-first-plugin&status=updated' ) ); exit; } add_action( 'admin_post_mfp_save', 'mfp_save_options' ); |
4‑3. セキュリティベストプラクティス
| 項目 | 推奨手法 |
|---|---|
| 関数名衝突防止 | プラグイン独自のプレフィックス(例: mfp_)を付与 |
| CSRF 対策 | wp_nonce_field() と wp_verify_nonce() を必ず使用 |
| 入力サニタイズ | sanitize_text_field(), intval() などでデータを浄化 |
| 出力エスケープ | esc_html(), esc_attr() で XSS を防止 |
4‑4. デバッグ・トラブルシューティング
- WP_DEBUG の有効化(前節参照)
- Query Monitor プラグインをインストールし、フック実行状況や DB クエリを可視化。
- ログ出力例
php
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( '[MyFirstPlugin] Plugin loaded at ' . current_time('mysql') );
}
- よくあるエラーと対処法
| エラーメッセージ | 原因例 | 確認ポイント |
|---|---|---|
Missing plugin header |
ヘッダーコメントが欠落または誤字 | ファイル冒頭の /** ... */ が正しいか |
Call to undefined function add_action() |
プラグインが直接アクセスされた | if ( ! defined('ABSPATH') ) exit; が機能しているか |
Nonce verification failed. |
フォーム送信時に nonce が不一致 | wp_nonce_field() と wp_verify_nonce() のキー名が揃っているか |
4‑5. まとめ
- コードは 100 行程度 に収めても、フックとセキュリティ対策さえ抑えていれば実務で使えるプラグインになります。
- 今後は クラス化・名前空間化 を取り入れ、機能をモジュール単位に分割すると保守が楽になります。
5. プラグインの配布準備と公開フロー
5‑1. 結論
readme.txt(WordPress.org 標準フォーマット)を作成し、SVN にコミットすればプラグインは世界中に公開できます。
5‑2. 背景
- WordPress.org のプラグインディレクトリは GPLv2+ ライセンスが必須です。
readme.txtは審査時の重要項目であり、正しいフォーマットが無いと承認が下りません。
5‑3. readme.txt の雛形
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
=== My First Plugin === Contributors: yourname Tags: shortcode, admin-menu, greeting Requires at least: 6.4 Tested up to: 6.5 Stable tag: 1.0.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Requires PHP: 8.2 Text Domain: my-first-plugin カスタムショートコードと管理画面メニューを提供する超初心者向けプラグインです。 == Description == このプラグインは `[hello_world name="WordPress"]` ショートコードで簡単に挨拶文を表示し、管理画面からテキストを変更できます。 PHP 8.2 と WordPress 6.4+ に対応しています。 == Installation == 1. `wp-content/plugins/` ディレクトリにアップロード(または WordPress 管理画面の「プラグイン」→「新規追加」で検索)。 2. 「有効化」をクリック。 3. 設定ページ → 「First Plugin」から挨拶文を入力。 == Frequently Asked Questions == = ショートコードはどう使うのですか? = `[hello_world name="WordPress"]` のように投稿・固定ページ内に記述してください。 = 管理画面で設定したテキストが反映されません。 = プラグインを有効化後、**キャッシュプラグイン** が無効か確認し、ブラウザのキャッシュもクリアしてください。 == Screenshots == 1. 設定画面(管理メニュー) == Changelog == = 1.0.0 (2026‑04‑19) = * 初版リリース。ショートコードと設定ページを実装。 |
5‑4. SVN による公開手順(2025 年以降の標準フロー)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# ① WordPress.org アカウントでログインし、プラグイン名「my-first-plugin」でリポジトリ作成 # → 自動的に https://plugins.svn.wordpress.org/my-first-plugin/ が生成 # ② ローカルへチェックアウト svn checkout https://plugins.svn.wordpress.org/my-first-plugin/ my-first-plugin cd my-first-plugin/trunk # 作業対象は trunk ディレクトリ # ③ 必要ファイルを配置(例: my-first-plugin.php, readme.txt, assets/ 等) cp -R /path/to/local/plugin/* . # ④ 追加・コミット svn add * svn commit -m "Initial release of My First Plugin v1.0.0" # ⑤ タグ作成(バージョン管理のために tags ディレクトリへコピー) cd .. cp -R trunk tags/1.0.0 svn add tags/1.0.0 svn commit -m "Tag 1.0.0" |
ポイント
-trunkが「開発中の最新版」、tags/x.x.xが「リリース版」として扱われます。
- コミット後に WordPress.org の審査が走り、数時間以内にプラグインページが公開されます。
5‑6. 配布後にやるべきこと
| タスク | 内容 |
|---|---|
| バージョン管理 | readme.txt の Stable tag と svn tags/ を同期させる |
| アップデート通知 | 新機能追加時は Version: と Stable tag を更新し、tags/ に新しいディレクトリを作成 |
| サポート体制 | WordPress.org の「Support」タブで質問に回答。FAQ を充実させると負荷が減ります |
| セキュリティチェック | 定期的に WPScan や CodeQL で脆弱性を検出し、必要ならパッチを提供 |
5‑7. まとめ
- 正しい
readme.txtと SVN コミット があれば、世界中の WordPress ユーザーにプラグインが届きます。 - 公開後はバージョン管理とユーザーサポートを継続し、信頼性の高いプラグインへ成長させましょう。
6. 総括
| 項目 | 要点 |
|---|---|
| プラグインの基礎 | ヘッダーとフォルダ構造だけで有効化可能。フックシステムが拡張の鍵 |
| ローカル環境 | MAMP/XAMPP + WP‑CLI で数分に WordPress 8.2 環境を構築 |
| PHP の応用 | 名前空間・オートローディングでコードをモジュール化、保守性向上 |
| 最初の実装 | ショートコードと管理画面メニューだけでも機能的なプラグインが完成 |
| デバッグ | WP_DEBUG と Query Monitor でエラーを可視化 |
| 配布 | readme.txt を整備し SVN にコミットすれば WordPress.org に公開可能 |
これらの手順を順に実践すれば、超初心者でも自分だけのプラグインを作成・テスト・公開できるようになります。ぜひ本記事のサンプルコードとチェックリストを活用し、最初の一歩を踏み出してみてください! 🚀