ヘッダーのロゴ

すぐに仕事で使えるIT技術情報メディア

すぐ作れる!WordPressの本格的なプラグインを自作する方法やメリット等を徹底解説

投稿日:2024年04月19日(金) 更新日:2024年05月15日(水)
すぐ作れる!WordPressの本格的なプラグインを自作する方法やメリット等を徹底解説|WordPress MAGAZINE ワードプレスマガジン|すぐに仕事で使えるIT技術情報メディア

みなさんこんにちは!エンジニアの高澤です!

今回はWordPressの本格的なプラグインを自作する方法を徹底解説していきたいと思います。

WordPressのプラグインを自作するなんて難しいのではないか!?と思われる方もいらっしゃるかと思いますが、当記事の解説に沿って手を動かしていただければ決して難しくはありません!

当記事では初心者エンジニアの方でも無理なく読み進められるようにし、また上級エンジニアの方にも学び直しや仕事でのプラグイン開発時の雛形として繰り返しお役立ていただけるように構成いたしました。

プラグイン開発ができるようになればよりできることの幅が広がり、テーマ制作においても高度な機能を実装することができプラグイン開発のノウハウが多方面で活きてきます。

自分でいうのもなんですが、当記事は特に力を入れて執筆した内容となっておりますので、よろしければぜひご確認いただけましたら幸いです。

目次

どんなプラグインを開発するのか?

それではまずはどんなプラグインを開発するのかをここで事前に解説しておきたいと思います。

今回実装するのは「ラジオボタン」「チェックボックス」「テキスト」「画像」の4つのデータタイプのデータを保存することができるオプションページ(設定ページ)機能を追加できる実装になります。

保存したデータを表示するためのショートコードも実装し、保存も表示もどちらもできるようにしたいと思います。

画像のアップロード機能にはWordPressによって提供されているメディアアップローダー機能を実装してアップロードしやすくしております。

どれも基本的な機能となっておりまして、当記事の内容を実装することができれば今後プラグインを開発する上で応用が効くように構成させていただいております。

読み進めるだけでプラグインが簡単に実装できてしまうので、よろしければぜひ読み進めていただければと思います。

プラグインとは

プラグインとは、WordPressに標準の機能にさらに機能を追加して拡張してくれるソフトウェアのことをいいます。

世界中のエンジニアがプラグインを開発して公開しており、WordPressの管理画面からクリックするだけで無料でインストールすることができ、簡単に機能を追加することが可能です。

WordPressのプラグインは、PHPやJavaScriptなどのプログラミング言語で書かれたファイルの集まりであり、WordPressの機能を簡単にカスタマイズできるようになっています。

プラグインの主な機能

これからプラグインを自作する際に実装のイメージがずれないように、事前にプラグインの機能をしっかり把握しておきましょう。

主な機能としては以下の内容になります。

  • 新しい機能の追加
  • 既存機能の拡張
  • テーマの機能拡張
  • セキュリティ強化

それぞれ解説いたします。

新しい機能の追加

WordPressに標準で備わっていない機能を追加することができます。例えば、コンタクトフォームやSEO対策のための機能などを追加することができます。

既存機能の拡張

WordPressにすでに備わっている機能をより強力にしたり、カスタマイズしたりすることができます。例えば、投稿やページのレイアウトをカスタマイズしたり、管理画面の機能を拡張したりすることができます。

テーマの機能拡張

WordPressのテーマをより柔軟にするための機能を追加することができます。例えば、カスタムウィジェットや独自のショートコードを追加して、テーマの機能を拡張することができます。

セキュリティ強化

WordPressのセキュリティを強化するための機能を追加することができます。例えば、不正アクセスを防止するための機能や、セキュリティホールを修正するための機能などがあります。

プラグインを自作できるメリット

次は、プラグインを自作できるメリットについて解説したいと思います。

筆者が考えるメリットは以下になります。

  • WordPress構築の幅が一気に広がる
  • 作成したプラグインを世界に公開できる
  • 有料プラグインとして販売できる
  • 開発者としてブランディングできる

それぞれ解説いたします。

WordPress構築の幅が一気に広がる

WordPressプラグインの開発により、WordPressの機能や機能性を独自のニーズや要件に合わせて拡張できます。

たとえば、カスタム投稿タイプやカスタムフィールドを追加したり、特定の機能を自動化したりするプラグインを開発することで、WordPressサイトの柔軟性や機能性が向上します。

プラグインを使うことで、WordPressをさまざまな用途に活用することが可能になります。

作成したプラグインを世界に公開できる

WordPressプラグインをWordPress.orgの公式プラグインディレクトリや他のオンラインマーケットプレイスに公開することができます。

これにより、世界中のWordPressユーザーに自分のプラグインを提供することができます。

プラグインを公開することで、ユーザーからのフィードバックを受け取り、プラグインの品質や機能を向上させることができます。

有料プラグインとして販売できる

自分の開発したプラグインを有料で販売することができます。

WordPressのプラグイン市場は大きく、需要の高いプラグインや特定のニーズに応えるプラグインは有料でも需要があります。

有料プラグインを販売することで、開発者は収益を得ることができます。

また、サポートやメンテナンスを提供することで、顧客満足度を高めることができます。

開発者としてブランディングできる

WordPressプラグインの開発は、開発者としてのブランディングや知名度を高めるための有効な手段です。

優れたプラグインを開発することで、WordPressコミュニティや業界内での認知度を高めることができます。

また、公開したプラグインに自分の名前や会社名を表示することで、プロフェッショナリズムや信頼性をアピールすることができます。

プラグイン開発の流れ

次は、プラグイン開発の流れについて解説したいと思います。

流れは以下になります。

  • アイデアの検討
  • プラグインの設計
  • 開発
  • テスト
  • リリース
  • メンテナンス

それぞれ解説いたします。

アイデアの検討

まずは、開発したいプラグインのアイデアを明確にしましょう。他のプラグインとの差別化やニーズの検討、機能のスコープなどを考えます。

プラグインの設計

次に、プラグインの設計を行います。これには、機能の構造化やデータベースの設計、使用するテクノロジーなどを含みます。プラグインの構成要素やクラスの設計を考えることも含まれます。

開発

プラグインの開発を開始します。PHPやJavaScriptなどのプログラミング言語を使用して、プラグインの機能を実装します。必要に応じて、CSSやHTMLを使用して、フロントエンドのデザインを調整することもあります。

当記事ではこの部分中心に解説いたします。

テスト

開発したプラグインをテストします。動作の確認やバグの修正、セキュリティの確認などを行います。WordPressの最新バージョンや異なる環境でのテストも重要です。

リリース

プラグインが完成したら、WordPress.orgのプラグインディレクトリにリリースすることができます。また、GitHubなどのプラットフォームでソースコードを公開することもできます。リリース前には、プラグインのドキュメントや使い方の説明を記述しましょう。

メンテナンス

プラグインのメンテナンスを継続して行います。WordPressのアップデートやセキュリティの脆弱性への対応、ユーザーからのフィードバックの収集などが含まれます。必要に応じて新機能の追加やバグ修正なども行います。

プラグインを開発する方法

それでは早速プラグインを開発する方法について解説したいと思います。

当記事での具体的な開発の流れは以下になります。

  • プラグインの雛形を作成
  • プラグインファイルをアップロード
  • 第一段階PHP実装(機能の実装)
  • 第二段階PHP実装(リファクタリング・カプセル化)
  • ショートコードの実装

上から順に解説していきます。

プラグインのファイル構成

まずは把握しておくべきこととして、プラグインのファイル構成についてご説明しておきます。

当記事では以下のディレクトリ・ファイル構成でプラグインを作成します。

上記のようにディレクトリとファイルを作成しましょう。

PCのデスクトップ上で作成していただくイメージで大丈夫です。

「wp-mag-2404-plugin」という名前でディレクトリファイルを一つ作成してください。

作成したら次は.phpファイル形式で「wp-mag-2404-plugin.php」と「wp-mag-2404-plugin-shortcode.php」という名前でPHPファイルを2つ作成してください。

「wp-mag-2404-plugin.php」はプラグインの本体のPHPファイルとして、「wp-mag-2404-plugin-shortcode.php」はショートコードを実装するためのPHPファイルとして作成します。

最後に「wp-mag-2404-plugin.php」と「wp-mag-2404-plugin-shortcode.php」を「wp-mag-2404-plugin」ディレクトリに入れてください。

これでプラグインを構成するファイルの作成は完了です。

次からはこの作成したPHPファイルにコードを記述していきます。

プラグインの雛形を作成

次はプラグインの雛形を作成します。

PHPファイルの「wp-mag-2404-plugin.php」に以下のコードをコピー&ペーストしてください。

<?php
/*
Plugin Name: WordPress MAGAZINE 2404 Plugin
Plugin URI: 
Description: 
Author: WordPress MAGAZINE Developer
Version: 1.0.0
Author URI: https://wordpress-mag.com/
*/


上記のコードは、WordPressプラグインの基本的な情報を含むプラグインのヘッダー情報です。この情報は、WordPressがプラグインを認識し、管理画面で表示するために使用されます。

それぞれの内容は以下になりますので、ご確認ください。

Plugin Nameプラグインの名前を指定します。
Plugin URIプラグインに関連するウェブサイトやドキュメントのURLを指定します。
Descriptionプラグインの簡単な説明を記述します。
Authorプラグインの作者または開発者の名前を指定します。
Versionプラグインのバージョンを指定します。
Author URIプラグインの作者または開発者のウェブサイトやプロフィールのURLを指定します。

ペーストして保存したら、プラグインファイル「wp-mag-2404-plugin」をサーバーにアップロードしていきます。

プラグインファイルをアップロード

次はFTPソフトでサーバーのFTP接続して以下のパス通りに「plugins」ファイル内に「wp-mag-2404-plugin」ごとアップロードしてください。

/【サイトディレクトリ】/wp-content/plugins

FileZillaというFTPソフトでアップロードする際のイメージは下図になります。

アップロードが完了したら、WordPressの管理画面左メニュー「プラグイン」→「インストール済みプラグイン」をクリックしてインストール済みプラグインの一覧画面を開いてください。

すると下図のように「WordPress MAGAZINE 2404 Plugin」というプラグイン名でインストール済みになっていることを確認できるかと思います。こちらを「有効化」してください。

有効化をしていただいたら処理のコードをいっさい記述していないので何が起こるわけでもありませんが、エラーなどが起こらなければ一旦プラグインとして最低限の実装は完了です。

第一段階のPHP実装(機能を実装)

次は、プラグインの処理を記述して実装したいと思います。

以下のコードを「wp-mag-2404-plugin.php」にコピー&ペーストしてください。

<?php
// 設定ページのコンテンツを表示する関数
function my_custom_plugin_settings_page() {
    wp_enqueue_media();
    ?>
    <div class="wrap">
        <h2>設定</h2>
        <form method="post" action="options.php">
            <?php settings_fields('my_custom_plugin_settings_group'); ?>
            
            <h3>ラジオボタン</h3>
            <label><input type="radio" name="sample_radio_data" value="sample_radio_data_1" <?php checked(get_option('sample_radio_data'), 'sample_radio_data_1', true); ?>> ラジオボタン1</label><br>
            <label><input type="radio" name="sample_radio_data" value="sample_radio_data_2" <?php checked(get_option('sample_radio_data'), 'sample_radio_data_2'); ?>> ラジオボタン2</label><br>
            <br>

            <h3>チェックボックス</h3>
            <label><input type="checkbox" name="sample_checkbox_data[]" value="sample_checkbox_data_1" <?php checked( !empty(get_option('sample_checkbox_data')) && in_array( 'sample_checkbox_data_1', get_option('sample_checkbox_data') ) ); ?>> オプション1</label><br>
            <label><input type="checkbox" name="sample_checkbox_data[]" value="sample_checkbox_data_2" <?php checked( !empty(get_option('sample_checkbox_data')) && in_array( 'sample_checkbox_data_2', get_option('sample_checkbox_data') ) ); ?>> オプション2</label><br>
            <br>

            <h3>テキストボックス</h3>
            <label><input type="text" name="sample_text_data" value="<?php echo esc_attr( get_option('sample_text_data') ); ?>"><span style="display:inline-block;margi-left:4px;"></span></label>
            <br>

            <h3>画像アップロード</h3>
            <?php
            $image_url = get_option('sample_image_data');
            ?>
            <input type="text" name="sample_image_data" id="sample_image_data" value="<?php echo esc_attr($image_url); ?>" readonly>
            <input type="button" id="upload_image_button" class="button" value="画像をアップロード">
            <div id="image_preview" style="margin-top:10px;">
                <?php if ($image_url) : ?>
                    <img src="<?php echo esc_url($image_url); ?>" style="max-width: 200px;">
                <?php endif; ?>
            </div>
            <span id="upload_image_remove_button" style="display:inline-block;cursor:pointer;margin-top:5px;">
                画像を削除
            </span>
            <script>
            (function ($) {
                var mediaUploader;
                $('#upload_image_button').on('click', function (e) {
                    e.preventDefault();
                    if (mediaUploader) {
                        mediaUploader.open();
                        return;
                    }
                    // メディアアップローダーを呼び出し
                    var mediaUploader = wp.media({
                        title: 'Select Image',
                        library: { type: 'image' },
                        multiple: false,
                    });
                    // 画像が選択された時の処理
                    mediaUploader.on('select', function () {
                        var attachment = mediaUploader.state().get('selection').first().toJSON();
                        $('#sample_image_data').val(attachment.url);
                        $('#image_preview').html('<img src="' + attachment.url + '" style="max-width: 200px;">');
                    });
                    // メディアアップローダーを開く
                    mediaUploader.open();
                });
            })(jQuery);

            (function ($) {
                $('#upload_image_remove_button').on('click', function(e){
                    $('#sample_image_data').val("");
                    $('#image_preview').html("");
                });
            })(jQuery);
            </script>
            <br>

            <?php submit_button(); ?>
        </form>
    </div>
    <?php
}
// 設定ページを追加するアクションフック
add_action('admin_menu', 'my_custom_plugin_menu');

// 設定ページをメニューに追加する関数
function my_custom_plugin_menu() {
    add_options_page(
        'オリジナルの設定', // ページタイトル
        'オリジナルの設定', // メニュータイトル
        'manage_options', // 権限
        'my-custom-plugin-settings', // ページスラッグ
        'my_custom_plugin_settings_page' // コールバック関数
    );
}
// 設定フィールドを登録するフック
add_action('admin_init', 'my_custom_plugin_register_settings');

// 設定フィールドを登録する関数
function my_custom_plugin_register_settings() {
    register_setting('my_custom_plugin_settings_group', 'sample_radio_data');
    register_setting('my_custom_plugin_settings_group', 'sample_checkbox_data');
    register_setting('my_custom_plugin_settings_group', 'sample_text_data');
    register_setting('my_custom_plugin_settings_group', 'sample_image_data');
}

注意点としては先ほど記述したプラグインのヘッダー情報を削除しないようにしてください。

この時点で、管理画面左メニューの「設定」に「オリジナルの設定」が追加され、自作したプラグイン独自のオプションページ(設定ページ)が追加されていることが確認できるかと思います。

「ラジオボタン」「チェックボックス」「テキスト」「画像」の4つのデータタイプを実装しており、それぞれデータを保存することができるようになっております。

ここまでで第一段階のPHP実装は完了し、プラグインとして成立して実装が完了いたしました。

次の内容からは、一旦できた現状のプラグインをよりセキュリティを意識したリファクタリングをして、また、ショートコードで独自のオプションページにて設定した内容を出力して表示できるようにしていきたいと思います。

第二段階のPHP実装(リファクタリング・カプセル化)

次は第二段階のPHP実装をおこなっていきたいと思います。

以下のコードは先ほど実装したコードをクラスでカプセル化したものです。

クラス名は CustomPluginSettingsPage としています。これにより、関連する機能がひとまとめになり、コードの構造化と保守性が向上します。

<?php
class CustomPluginSettingsPage {
    
    public function __construct() {
        add_action('admin_menu', array( $this, 'add_settings_page' ) );
        add_action('admin_init', array( $this, 'register_settings' ) );

        // 同じ階層にあるPHPファイルを読み込む
        require_once plugin_dir_path( __FILE__ ) . 'wp-mag-2404-plugin-shortcode.php';
    }

    // 設定ページを追加するメソッド
    public function add_settings_page() {
        add_options_page(
            'オリジナルの設定', // ページタイトル
            'オリジナルの設定', // メニュータイトル
            'manage_options', // 権限
            'my-custom-plugin-settings', // ページスラッグ
            array( $this, 'settings_page_content' ) // コールバック関数
        );
    }

    // 設定ページのコンテンツを表示するメソッド
    public function settings_page_content() {
        wp_enqueue_media();
        ?>
        <div class="wrap">
            <h2>設定</h2>
            <form method="post" action="options.php">
                <?php settings_fields('my_custom_plugin_settings_group'); ?>
                
                <h3>ラジオボタン</h3>
                <label><input type="radio" name="sample_radio_data" value="sample_radio_data_1" <?php checked(get_option('sample_radio_data'), 'sample_radio_data_1', true); ?>> ラジオボタン1</label><br>
                <label><input type="radio" name="sample_radio_data" value="sample_radio_data_2" <?php checked(get_option('sample_radio_data'), 'sample_radio_data_2'); ?>> ラジオボタン2</label><br>
                <br>

                <h3>チェックボックス</h3>
                <label><input type="checkbox" name="sample_checkbox_data[]" value="sample_checkbox_data_1" <?php checked( !empty(get_option('sample_checkbox_data')) && in_array( 'sample_checkbox_data_1', get_option('sample_checkbox_data') ) ); ?>> オプション1</label><br>
                <label><input type="checkbox" name="sample_checkbox_data[]" value="sample_checkbox_data_2" <?php checked( !empty(get_option('sample_checkbox_data')) && in_array( 'sample_checkbox_data_2', get_option('sample_checkbox_data') ) ); ?>> オプション2</label><br>
                <br>

                <h3>テキストボックス</h3>
                <label><input type="text" name="sample_text_data" value="<?php echo esc_attr( get_option('sample_text_data') ); ?>"><span style="display:inline-block;margi-left:4px;"></span></label>
                <br>

                <h3>画像アップロード</h3>
                <?php
                $image_url = get_option('sample_image_data');
                ?>
                <input type="text" name="sample_image_data" id="sample_image_data" value="<?php echo esc_attr($image_url); ?>" readonly>
                <input type="button" id="upload_image_button" class="button" value="画像をアップロード">
                <div id="image_preview" style="margin-top:10px;">
                    <?php if ($image_url) : ?>
                        <img src="<?php echo esc_url($image_url); ?>" style="max-width: 200px;">
                    <?php endif; ?>
                </div>
                <span id="upload_image_remove_button" style="display:inline-block;cursor:pointer;margin-top:5px;">
                    画像を削除
                </span>
                <script>
                (function ($) {
                    var mediaUploader;
                    $('#upload_image_button').on('click', function (e) {
                        e.preventDefault();
                        if (mediaUploader) {
                            mediaUploader.open();
                            return;
                        }
                        // メディアアップローダーを呼び出し
                        var mediaUploader = wp.media({
                            title: 'Select Image',
                            library: { type: 'image' },
                            multiple: false,
                        });
                        // 画像が選択された時の処理
                        mediaUploader.on('select', function () {
                            var attachment = mediaUploader.state().get('selection').first().toJSON();
                            $('#sample_image_data').val(attachment.url);
                            $('#image_preview').html('<img src="' + attachment.url + '" style="max-width: 200px;">');
                        });
                        // メディアアップローダーを開く
                        mediaUploader.open();
                    });
                })(jQuery);

                (function ($) {
                    $('#upload_image_remove_button').on('click', function(e){
                        $('#sample_image_data').val("");
                        $('#image_preview').html("");
                    });
                })(jQuery);
                </script>
                <br>

                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }

    // 設定フィールドを登録するメソッド
    public function register_settings() {
        register_setting('my_custom_plugin_settings_group', 'sample_radio_data');
        register_setting('my_custom_plugin_settings_group', 'sample_checkbox_data');
        register_setting('my_custom_plugin_settings_group', 'sample_text_data');
        register_setting('my_custom_plugin_settings_group', 'sample_image_data');
    }
}

// インスタンス化してメニュー追加
new CustomPluginSettingsPage();

このようにクラスでコードをカプセル化することで、関連する機能がグループ化され、コードの見通しがよくなります。

また、複数のプラグインやテーマで同様の設定ページを作成する場合に、再利用性が向上します。

ショートコードの実装

次はこれまで実装したシステムによって保存されたデータを表示させるためのショートコードを実装していきたいと思います。

以下のコードを「wp-mag-2404-plugin-shortcode.php」にコピー&ペーストしてください。

<?php
// ショートコード関数の定義
function custom_plugin_settings_page_radio_function() {
    $sample_radio_data = get_option('sample_radio_data');
    ob_start();
        if($sample_radio_data == 'sample_radio_data_1'):
    ?>
    <div style="background:blue;color:white;">
        <?php echo $sample_radio_data; ?>
    </div>
    <?php
        elseif($sample_radio_data == 'sample_radio_data_2'):
    ?>
    <div style="background:orange;color:white;">
        <?php echo $sample_radio_data; ?>
    </div>
    <?php
        endif;
    return ob_get_clean();
}
// ショートコードを登録
add_shortcode('sample_radio_data', 'custom_plugin_settings_page_radio_function');



// ショートコード関数の定義
function custom_plugin_settings_page_checkbox_function() {
    $sample_checkbox_data = get_option('sample_checkbox_data');
    ob_start();
        if(is_array($sample_checkbox_data) && !empty($sample_checkbox_data)):
        foreach($sample_checkbox_data as $val):
    ?>
    <div style="background:green;color:white;">
        <?php echo $val; ?>
    </div>
    <?php
        endforeach;
        endif;
    return ob_get_clean();
}
// ショートコードを登録
add_shortcode('sample_checkbox_data', 'custom_plugin_settings_page_checkbox_function');



// ショートコード関数の定義
function custom_plugin_settings_page_text_function() {
    $sample_text_data = get_option('sample_text_data');
    ob_start();
        if(!empty($sample_text_data)):
    ?>
    <div style="background:red;color:white;">
        <?php echo $sample_text_data; ?>
    </div>
    <?php
        endif;
    return ob_get_clean();
}
// ショートコードを登録
add_shortcode('sample_text_data', 'custom_plugin_settings_page_text_function');



// ショートコード関数の定義
function custom_plugin_settings_page_img_function() {
    $sample_image_data = get_option('sample_image_data');
    ob_start();
        if(!empty($sample_image_data)):
    ?>
    <div>
        <img src="<?php echo $sample_image_data; ?>">
    </div>
    <?php
        endif;
    return ob_get_clean();
}
// ショートコードを登録
add_shortcode('sample_image_data', 'custom_plugin_settings_page_img_function');

ペーストして保存していただくと、保存した「ラジオボタン」「チェックボックス」「テキスト」「画像」のそれぞれのデータをショートコードによって表示できるようになりました。

ショートコードとしてデータを表示する場合はそれぞれ以下のショートコードをお使いください。

// ラジオボタンの保存したデータを表示するショートコード
[sample_radio_data]

// チェックボックスの保存したデータを表示するショートコード
[sample_checkbox_data]

// テキストの保存したデータを表示するショートコード
[sample_text_data]

// 画像の保存したデータを表示するショートコード
[sample_image_data]

上記は投稿編集画面の本文エディタに埋め込むことができるショートコードで、PHPテンプレートに記述して実装する場合は以下のようにdo_shortcode()関数を使用します。

<?php
// ラジオボタンの保存したデータを表示するショートコード
echo do_shortcode('[sample_radio_data]');

// チェックボックスの保存したデータを表示するショートコード
echo do_shortcode('[sample_checkbox_data]');

// テキストの保存したデータを表示するショートコード
echo do_shortcode('[sample_text_data]');

// 画像の保存したデータを表示するショートコード
echo do_shortcode('[sample_image_data]');

実際に実装してみて、それぞれ表示を確認していただければと思います。

これでプラグインの自作する方法の解説は以上になります。お疲れ様でした!

あとは当記事で開発したプラグインをご自身の自由にカスタマイズしてオリジナルのプラグインを開発したり、高度なテーマ開発などのお役立ていただけましたら幸いです!

筆者自身も当記事はずっと使い続けるかと思います。

プラグイン一覧画面に独自のリンクメニューを追加する方法

次にプラグイン一覧画面に独自のリンクメニューを追加する方法を解説したいと思います。

具体的には以下のイメージになります。

上図のように、プラグインを有効化したときによくあるプラグイン独自の「設定」や「サポート」といったリンクテキストを実装するという内容になります。

このリンクテキストを実装することができれば、プラグイン独自の設定ページの導線を設定できたり、ご自身で立ち上げたプラグインドキュメントサイトへアクセスさせたりすることが可能となります。

それでは早速実装してみましょう。

以下のコードをプラグインのPHPファイル(今回の場合は「wp-mag-2404-plugin.php」)の任意の箇所にコピー&ペーストしてください。

<?php
//------------------------------------
// プラグイン一覧:メニュー追加
//------------------------------------
// プラグインのアクションリンクを追加するための関数
function add_action_links($actions) {
    // プラグインの設定ページへのリンク
    $menu_settings_url = '<a href="' . esc_url(admin_url('options-general.php')) . '">設定</a>';
    // サポートページへのリンク
    $menu_support_url = '<a href="https://example.com/support">サポート</a>';

    // サポートページへのリンクを配列の先頭に追加
    array_unshift($actions, $menu_support_url);
    // プラグインの設定ページへのリンクを配列の先頭に追加
    array_unshift($actions, $menu_settings_url);

    return $actions;
}
// プラグインのアクションリンクを追加するフィルターフックに関数を追加
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'add_action_links');

上記コードをペーストして保存していただけましたら、下図のように「設定」と「サポート」のリンクテキスト2つが追加されていることが確認できるかと思います。

リンクテキストは現状2つありますが、リンクテキストを追加したい場合はシンプルに以下のように既存のコードをコピペして複製していただき、内容をカスタマイズしていただければ実装できます。

変更箇所は2つありまして、まず一つは以下のようにリンクテキスト自体を追加実装します。

<?php
// プラグインの設定ページへのリンク
$menu_settings_url = '<a href="' . esc_url(admin_url('options-general.php?page=my-custom-plugin-settings')) . '">設定</a>';
// サポートページへのリンク
$menu_support_url = '<a href="https://example.com/support" target="_blank">サポート</a>';

// ↓以下のように上記コードをコピペして複製し内容を書き換え
// サポートページ2へのリンク
$menu_support2_url = '<a href="https://example.com/support2">サポート2</a>';

上記HTMLのaタグの内容をカスタマイズしていただき、独自のリンクテキストを実装してください。

$menu_settings_url変数に代入しているesc_url(admin_url(‘options-general.php?page=my-custom-plugin-settings’))のadmin_url関数の引数の部分は下図のプラグインで実装した設定ページのURLに対応しておりますので、リンクをコピーしてコードに反映させてください。

もう一つは、以下のようにコピペしたコードを既存のコードより手前にペーストしていただき、内容をカスタマイズしてください。

<?php
// ↓以下のように下記コードをコピペして複製し内容を書き換え
// サポートページ2へのリンクを配列の先頭に追加
array_unshift($actions, $menu_support2_url);

// サポートページへのリンクを配列の先頭に追加
array_unshift($actions, $menu_support_url);
// プラグインの設定ページへのリンクを配列の先頭に追加
array_unshift($actions, $menu_settings_url);

追加のカスタマイズができましたら、下図のようにリンクテキストが新たに追加されているのが確認できるかと思います。

これで実装自体は完了です!次は仕上げにカプセル化していきます。

プラグイン一覧画面の独自のリンクテキスト実装後のカプセル化

それでは最後にリンクテキスト実装後のカプセル化のコードをカプセル化していきます。

以下のコードをまるまるプラグインの本体PHPファイル(今回の場合は「wp-mag-2404-plugin.php」)にごっそりコピー&ペーストしてください。

<?php
/*
Plugin Name: WordPress MAGAZINE 2404 Plugin
Plugin URI: 
Description: このプラグインは WordPress MAGAZINE Developer による独自の設定ページです。
Author: WordPress MAGAZINE Developer
Version: 1.0.0
Author URI: https://wordpress-mag.com/
*/
 

class CustomPluginSettingsPage {
    
    public function __construct() {
        add_action('admin_menu', array( $this, 'add_settings_page' ) );
        add_action('admin_init', array( $this, 'register_settings' ) );

        // プラグインのアクションリンクを追加するフィルターフックに関数を追加
        add_filter('plugin_action_links_' . plugin_basename(__FILE__), array( $this, 'add_action_links' ));

        // 同じ階層にあるPHPファイルを読み込む
        require_once plugin_dir_path( __FILE__ ) . 'wp-mag-2404-plugin-shortcode.php';
    }

    // 設定ページを追加するメソッド
    public function add_settings_page() {
        add_options_page(
            'オリジナルの設定', // ページタイトル
            'オリジナルの設定', // メニュータイトル
            'manage_options', // 権限
            'my-custom-plugin-settings', // ページスラッグ
            array( $this, 'settings_page_content' ) // コールバック関数
        );
    }

    // 設定ページのコンテンツを表示するメソッド
    public function settings_page_content() {
        wp_enqueue_media();
        ?>
        <div class="wrap">
            <h2>設定</h2>
            <form method="post" action="options.php">
                <?php settings_fields('my_custom_plugin_settings_group'); ?>
                
                <h3>ラジオボタン</h3>
                <label><input type="radio" name="sample_radio_data" value="sample_radio_data_1" <?php checked(get_option('sample_radio_data'), 'sample_radio_data_1', true); ?>> ラジオボタン1</label><br>
                <label><input type="radio" name="sample_radio_data" value="sample_radio_data_2" <?php checked(get_option('sample_radio_data'), 'sample_radio_data_2'); ?>> ラジオボタン2</label><br>
                <br>

                <h3>チェックボックス</h3>
                <label><input type="checkbox" name="sample_checkbox_data[]" value="sample_checkbox_data_1" <?php checked( !empty(get_option('sample_checkbox_data')) && in_array( 'sample_checkbox_data_1', get_option('sample_checkbox_data') ) ); ?>> オプション1</label><br>
                <label><input type="checkbox" name="sample_checkbox_data[]" value="sample_checkbox_data_2" <?php checked( !empty(get_option('sample_checkbox_data')) && in_array( 'sample_checkbox_data_2', get_option('sample_checkbox_data') ) ); ?>> オプション2</label><br>
                <br>

                <h3>テキストボックス</h3>
                <label><input type="text" name="sample_text_data" value="<?php echo esc_attr( get_option('sample_text_data') ); ?>"><span style="display:inline-block;margi-left:4px;"></span></label>
                <br>

                <h3>画像アップロード</h3>
                <?php
                $image_url = get_option('sample_image_data');
                ?>
                <input type="text" name="sample_image_data" id="sample_image_data" value="<?php echo esc_attr($image_url); ?>" readonly>
                <input type="button" id="upload_image_button" class="button" value="画像をアップロード">
                <div id="image_preview" style="margin-top:10px;">
                    <?php if ($image_url) : ?>
                        <img src="<?php echo esc_url($image_url); ?>" style="max-width: 200px;">
                    <?php endif; ?>
                </div>
                <span id="upload_image_remove_button" style="display:inline-block;cursor:pointer;margin-top:5px;">
                    画像を削除
                </span>
                <script>
                (function ($) {
                    var mediaUploader;
                    $('#upload_image_button').on('click', function (e) {
                        e.preventDefault();
                        if (mediaUploader) {
                            mediaUploader.open();
                            return;
                        }
                        // メディアアップローダーを呼び出し
                        var mediaUploader = wp.media({
                            title: 'Select Image',
                            library: { type: 'image' },
                            multiple: false,
                        });
                        // 画像が選択された時の処理
                        mediaUploader.on('select', function () {
                            var attachment = mediaUploader.state().get('selection').first().toJSON();
                            $('#sample_image_data').val(attachment.url);
                            $('#image_preview').html('<img src="' + attachment.url + '" style="max-width: 200px;">');
                        });
                        // メディアアップローダーを開く
                        mediaUploader.open();
                    });
                })(jQuery);

                (function ($) {
                    $('#upload_image_remove_button').on('click', function(e){
                        $('#sample_image_data').val("");
                        $('#image_preview').html("");
                    });
                })(jQuery);
                </script>
                <br>

                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }

    // 設定フィールドを登録するメソッド
    public function register_settings() {
        register_setting('my_custom_plugin_settings_group', 'sample_radio_data');
        register_setting('my_custom_plugin_settings_group', 'sample_checkbox_data');
        register_setting('my_custom_plugin_settings_group', 'sample_text_data');
        register_setting('my_custom_plugin_settings_group', 'sample_image_data');
    }

    //------------------------------------
    // プラグイン一覧:メニュー追加
    //------------------------------------
    // プラグインのアクションリンクを追加するための関数
    public function add_action_links($actions) {
        // プラグインの設定ページへのリンク
        $menu_settings_url = '<a href="' . esc_url(admin_url('options-general.php?page=my-custom-plugin-settings')) . '">設定</a>';
        // サポートページへのリンク
        $menu_support_url = '<a href="https://example.com/support" target="_blank">サポート</a>';

        // サポートページへのリンクを配列の先頭に追加
        array_unshift($actions, $menu_support_url);
        // プラグインの設定ページへのリンクを配列の先頭に追加
        array_unshift($actions, $menu_settings_url);

        return $actions;
    }
}

// インスタンス化してメニュー追加
new CustomPluginSettingsPage();

上記コードが最終的なプラグイン本体ファイルの完成形になります。

これで実装は完了です。お疲れ様でした!

プラグインのセキュリティを強化する実装

プラグインではセキュリティ周りの実装が欠かせません。

プラグインを実装する際に必要なセキュリティ周りの実装方法について解説いたします。

外部から直接PHPファイルにアクセスされる事を防ぐ実装

ここでは外部から直接PHPファイルにアクセスされる事を防ぐ実装方法について解説いたします。

結論、以下のプラグインヘッダ情報の記述の直下のコードが実装コードになります。

以下のコードをwp-mag-2404-plugin.phpに記述してください。

<?php
/*
Plugin Name: WordPress MAGAZINE 2404 Plugin
Plugin URI: 
Description: このプラグインは WordPress MAGAZINE Developer による独自の設定ページです。
Author: WordPress MAGAZINE Developer
Version: 1.0.0
Author URI: https://wordpress-mag.com/
*/
 
defined( 'ABSPATH' ) || exit; //外部からのアクセスを防止
//または if ( ! defined( 'ABSPATH' ) ) exit; 

ABSPATHは、WordPress がインストールされているディレクトリのフルパスを表す定数です。このディレクトリにはwp-load.phpまたはwp-config.phpがあります。

defined は、指定した名前の定数が存在するかどうかを調べる関数です。

このコードは、プラグインのファイルが直接アクセスされた場合の処理を行っています。もし、直接アクセスされた場合、wp-load.phpを通らないためABSPATHという定数が定義されていません。その場合、スクリプトを終了するために exit を実行しています。

これで外部からブラウザを通してプラグインファイルの中身を確認される心配がありません。

よろしければぜひ参考になさってください。

当記事で実装したプラグインのおさらい

最後に当記事で実装したプラグインのおさらいをしていきたいと思います。

当記事のプラグインは下図のようなファイル構成になっているかと思います。

そこまで複雑ではないかと思います。

当記事で作成したプラグインを今後より機能を拡張していく場合、ソースコードの分割によってPHPファイルはもっと増えたりして複雑になるかと思うので、基本だけは忘れずにご自身のプラグインを開発するようにしましょう。

これで本格的なプラグインの実装ができました。お疲れ様でした!

今後は当記事のプラグイン実装のソースコードやノウハウを活かして、ご自身でプラグインを開発したり、functions.phpを利用した高度なテーマ開発の実装にお役立ていただけましたら幸いです。

作成したプラグインをインストールする方法

ご自身で作成したプラグインをWordPressにインストールする方法は、以下の方法があります。

  • 管理画面から新規追加ページでドラッグ&ドロップ
  • FTPソフトからサーバーへアップロード
  • WordPress公式サイトへ公開

それぞれ解説いたします。

管理画面から新規追加ページでドラッグ&ドロップ

管理画面から新規追加ページでドラッグ&ドロップするという方法があります。

以下の手順にした従ってプラグインをアップロードしてください。

まずは下図のように作成したプラグインディレクトリファイルをzipファイルに圧縮してください。

プラグインはzipファイルにしなければWordPress管理画面へアップロードすることができません。

zipファイルに圧縮できたら、下図のように管理画面左メニュー「プラグイン」→「新規プラグインを追加」ボタンをクリックしてください。

すると下図のように「プラグインを追加」ページが表示されるので、「ファイルを選択」部分にzipファイルをドラッグ&ドロップしてください。

最後に「今すぐインストール」ボタンをクリックしていただけますと下図のようにプラグイン一覧画面に作成したプラグインがインストールされていることが確認できます。

ここで「有効化」をクリックしていただけますと、プラグインが無事追加されて機能を使用することができるようになります。

FTPソフトからサーバーへアップロード

「FTPソフトからサーバーへアップロード」に関しては単純にFileZillaなどのFTPソフトを使ってプラグインディレクトリファイルをアップロードするだけです。

当記事でいえば「wp-mag-2404-plugin」ディレクトリファイルですね。

下図のようにプラグインディレクトリファイルをごっそりサーバー内のWordPressの階層である「/wp-content/plugins/」アップロードしてください。

上図はFileZillaによるサーバーへのアップロードのイメージになります。

「/wp-content/plugins/」へのアップロードが完了したら、下図のようにプラグイン一覧管理画面にプラグインが追加されていることが確認できるかと思います。

ここで「有効化」をクリックしていただけますと、プラグインが無事追加されて機能を使用することができるようになります。

WordPress公式サイトへ公開

最後にWordPress公式サイトへ公開するという手段があります。

公開とは全世界の誰もがご自身で作成されたプラグインをインストールできるようにするということになります。

公開するには、特定の方法に従ってプラグインをWordPress公式にアップロードしてプラグイン自体に問題がないか審査期間が必要で、ハードルが高いため当記事では軽く触れる程度にいたします。

この内容を本格的に扱ってしまうと記事がとんでもない量になってしまうので、別途記事で解説いたしますのでチェックしていただくか、他技術サイトにてご確認いただけますと幸いです。

まとめ

これでWordPressの本格的なプラグインを自作する方法を徹底解説についての内容は以上になります。

プラグイン開発ができることは、さまざまな面で非常に有利に働きます。

自作のプラグインを世界に公開できたり、有料プラグインとして販売できたり、開発者としてブランディングできるなど非常にメリットがたくさんあります。

また普段のテーマ開発においてもプラグインの実装内容はfunctions.phpに記述して実装することができるので、高度なテーマ開発をおこなうことが可能となります。

よろしければぜひ当記事をご活用いただき、プラグイン開発のスキルを習得していただけますと幸いです。

執筆者

ワードプレスマガジン編集部 高澤 翔汰

歴4年目(2024年8月以降から5年目です)のエンジニアです!
CMSでのサイト構築とWebデザイン制作を兼任して4年目になります。
自作のiOSアプリ(iPhoneアプリ)やWordPressプラグインを開発することもあり、まだまだ現在進行形で勉強中です!