WordPressプラグインに構成可能なフィールドを追加するための3つのアプローチ

公開: 2022-03-10
クイックサマリー↬WordPressプラグインを作成した人なら誰でも、プラグインの動作を変更するための構成可能なフィールドを作成する必要があることを理解しています。 プラグインの構成可能なオプションには無数の用途があり、前述のオプションを実装する方法はほぼ同じです。 ご覧のとおり、WordPressを使用すると、プラグインの作成者は設定ページ内に独自のマークアップを作成できます。 副作用として、設定ページはプラグイン間で大きく異なる可能性があります。 この記事では、プラグインを構成可能にする3つの一般的な方法について説明します。 まず、設定ページを作成し、デフォルトのWordPress設定APIを使用してフィールドを作成します。 次に、カスタムハンドラーを使用してフィールドを設定する方法について説明します。 最後に、優れた構成可能フィールドプラグインAdvanced Custom Fields(ACF)を独自のプラグインに統合する方法を示します。

WordPressプラグインを作成した人なら誰でも、プラグインの動作を変更するための構成可能なフィールドを作成する必要があることを理解しています。 プラグインの構成可能なオプションには無数の用途があり、前述のオプションを実装する方法はほぼ同じです。 ご覧のとおり、WordPressを使用すると、プラグインの作成者は設定ページ内に独自のマークアップを作成できます。 副作用として、設定ページはプラグイン間で大きく異なる可能性があります。

この記事では、プラグインを構成可能にする3つの一般的な方法について説明します。 まず、設定ページを作成し、デフォルトのWordPress設定APIを使用してフィールドを作成します。

SmashingMagの詳細

  • カスタムフィールドでWordPressを拡張する
  • WordPressのカスタムフィールドハック
  • 独自のコントロールを使用して高度なカスタムフィールドを拡張する
  • カスタム投稿タイプの完全ガイド

次に、カスタムハンドラーを使用してフィールドを設定する方法について説明します。 最後に、優れた構成可能フィールドプラグインAdvanced Custom Fields(ACF)を独自のプラグインに統合する方法を示します。

ジャンプした後もっと! 以下を読み続けてください↓

これは長い投稿なので、主な各セクションへのリンクを含む目次を次に示します。

  • プラグインと設定ページの作成
  • アプローチ1:組み込みのWordPress機能を使用する
  • アプローチ2:カスタムフォームとハンドラーを設定する
  • アプローチ3:プラグインへのACF(高度なカスタムフィールド)の統合

コード例については、この投稿に付随するように設定したリポジトリを参照してください。

プラグインと設定ページの作成

最初に行う必要があるのは、プラグインをセットアップして設定ページを作成することです。 この記事で概説されている3つのアプローチはすべて、以下のプラグイン構造から始まります。 このプラグイン構造はオブジェクト指向であるため、プラグインが手続き的に記述されている場合は、独自のコードにいくつかの違いがある可能性があります。 アクションとフィルターのコールバック関数の形式に特に注意してください。

 /* Plugin Name: Smashing Fields Plugin description: >- Setting up configurable fields for our plugin. Author: Matthew Ray Version: 1.0.0 */ class Smashing_Fields_Plugin { // Our code will go here } new Smashing_Fields_Plugin();

クラス内に、設定ページを追加するためのアクションフックを追加します。

 public function __construct() { // Hook into the admin menu add_action( 'admin_menu', array( $this, 'create_plugin_settings_page' ) ); }

アクションのコールバックがcreate_plugin_settings_pageであることがわかるので、そのメソッドを作成しましょう。 注:コードにコンテキストを与えるために、引数を個別の名前付き変数として設定しましたが、メモリを節約するために関数に直接値を配置するだけで済みます。

 public function create_plugin_settings_page() { // Add the menu item and page $page_title = 'My Awesome Settings Page'; $menu_title = 'Awesome Plugin'; $capability = 'manage_options'; $slug = 'smashing_fields'; $callback = array( $this, 'plugin_settings_page_content' ); $icon = 'dashicons-admin-plugins'; $position = 100; add_menu_page( $page_title, $menu_title, $capability, $slug, $callback, $icon, $position ); }

詳細については、 add_menu_pageのWPコーデックスを参照してください。

この関数は、ページとメニュー項目を作成します。 ここで重要な部分は、スラッグ、機能、およびコールバック引数です。 後でフィールドを登録するために使用するスラッグなので、どこかに書き留めます。 機能を変更して、さまざまなユーザーレベルが設定ページにアクセスできるようにすることができます。 コールバックについては、まもなくそのメソッドを作成します。 dashiconクラスを関数に直接入れて、メニューのアイコンを変更することもできます。 最後の引数は、メニュー内のメニュー項目の位置です。 この番号をいじって、設定を落としたいメニューの場所を見つけてください。 注:10進値を使用して、他のメニュー項目との競合を回避できます。

次のステップは、設定ページのコールバックメソッドplugin_settings_page_contentを作成することです。

 public function plugin_settings_page_content() { echo 'Hello World!'; }

プラグインを保存してWordPress管理パネルを更新すると、次のように表示されます。

設定ページのレイアウトを開始
設定ページの開始状態。 (拡大版を表示)

設定ページがトップレベルのメニュー項目であることがわかります。 設定ページのニーズに基づいて、このままにしておくことをお勧めします。 ただし、プラグイン設定を別のメニュー項目の下に配置することもできます。 この場合、 create_plugin_settings_pageメソッドの最後の行を次のように変更するだけです。

 add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $slug, $callback );

ここでは、関数add_menu_pageadd_submenu_pageに変更し、新しい引数を追加しています。 その引数は、新しい設定ページの下にある親メニュー項目です。 add_submenu_pageのドキュメントでは、親メニュー項目とそのスラッグのかなり良いリストを見ることができます。 また、最後の2つの引数、 $icon$positionがなくなっていることもわかります。 サブメニューセクションが表示されたため、要素の位置を制御できなくなりました。 また、サブメニューには使用可能なアイコンがないため、その引数は必要ありません。

この新しいコードを保存すると、設定ページが[設定]メニュー項目の下に表示されます。

サブメニューページが設定中になりました
これで、設定ページが[設定]メニューの下に配置されました。 (拡大版を表示)

多くの場合、プラグイン設定ページを追加するのに最も適切な場所は、[設定]項目の下です。 WordPressコーデックスでは、「設定」セクションは「管理者のみが表示するプラグインオプションを表示する」ために使用されると説明されています。 ただし、これは単なるガイドラインであり、規則ではありません。

設定ページが設定され、アイテムを移動する方法がわかったので、フィールドでの作業を開始できます。 これまでに行った作業は、以下のさまざまな方法で再利用されます。

アプローチ1:組み込みのWordPress機能を使用する

コードを深く掘り下げる前に、このアプローチを使用することの長所と短所をいくつか見ていきましょう。

長所

  • 既存の設定ページに簡単に統合できます
  • 衛生状態はあなたのために行われます
  • コードはWordPressによって管理されているため、壊れることはほとんどありません
  • テーマとプラグインの両方に使用できます
  • 柔軟性、安全性、拡張性

短所

  • カスタムデータ検証は手動です
  • 高度なフィールドタイプ(リピーター、マップ、アップロードなど)は実装がより困難です

このアプローチはいつ使用する必要がありますか?

このアプローチは十分に柔軟性があるため、非常に単純な設定ページまたは非常に高度な設定ページ用にカスタマイズできます。 手動で何かを行うことを気にしない場合は、ほとんどの状況でこの方法を使用できます。

入門

このアプローチを使用するには、WordPress独自のオプションページが使用するのと同じマークアップに従う必要があります。 plugin_settings_page_contentメソッドを次のように変更する必要があります。

 public function plugin_settings_page_content() { ?> <div class="wrap"> <h2>My Awesome Settings Page</h2> <form method="post" action="options.php"> <?php settings_fields( 'smashing_fields' ); do_settings_sections( 'smashing_fields' ); submit_button(); ?> </form> </div> <?php }

上記のマークアップは、オプションページの作成に関するWordPressコーデックスから直接のものです。 メソッド名は、上記のadd_menu_page関数に入力したコールバック名と一致する必要があります。 ラッパーdivは、実際にはデフォルトのWordPressフォームと同じであり、これらのセクションからスタイルを取得します。 formタグは、WordPressのデフォルトのオプションフォームハンドラーを指しています。

PHPの3行は、いくつかのことを行います。

  • settings_fields関数は、基本的に残りのフィールドの参照です。 その関数に入力する文字列引数は、前に設定した$slug変数と一致する必要があります。これは、後でプラグインに登録するすべてのフィールドに含まれます。 この関数は、ナンス、フォームアクション、およびオプションページの他のいくつかのフィールドのいくつかの非表示の入力も出力します。
  • 次の関数do_settings_sectionsは、プラグインの他の場所に登録するセクションとフィールドのプレースホルダーです。
  • 最後の関数submit_buttonは、送信入力を出力しますが、ページのステータスに基づいていくつかのクラスも追加します。 submit_button関数に渡したい他の引数があるかもしれません。 それらはコーデックスで概説されています。

設定ページを更新すると、次のようなものが表示されます。

空白のWordPress設定ページ
セクションとフィールドを登録する前の設定ページ。

少しまばらに見えます! それでは、フィールドの設定を始めましょう。

セクションとフィールド

WordPressはオプションページをセクションに分けています。 各セクションには、関連付けられたフィールドのリストを含めることができます。 フィールドの追加を開始する前に、プラグインにセクションを登録する必要があります。 コンストラクター関数に次のコードを追加します。

 add_action( 'admin_init', array( $this, 'setup_sections' ) );

このフックは、ページのセクションを設定します。 コールバックのコードは次のとおりです。

 public function setup_sections() { add_settings_section( 'our_first_section', 'My First Section Title', false, 'smashing_fields' ); }

最初の引数はセクションの一意の識別子であり、セクションに割り当てるフィールドにこれを使用します。 これらの識別子は、このページのすべての新しいセクションで一意である必要があります。 次の引数は、セクションの上に生成されるタイトルです。好きなように作成できます。 3番目の引数はコールバックです。 現在、 falseに設定していますが、すぐに再検討します。 4番目の引数は、オプションが追加されるオプションページです(以前の$slug変数)。

では、なぜコールバックにfalseがあるのでしょうか。 ドキュメントを使用してWordPressオプションを設定するときにあまり明確ではないことは、複数のセクションがコールバックを共有できることです。 多くの場合、コールバックを設定すると、フックとコールバックの間に1対1の関係があります。 例として、同じコールバックで3つのセクションを作成してみましょう。

 public function setup_sections() { add_settings_section( 'our_first_section', 'My First Section Title', array( $this, 'section_callback' ), 'smashing_fields' ); add_settings_section( 'our_second_section', 'My Second Section Title', array( $this, 'section_callback' ), 'smashing_fields' ); add_settings_section( 'our_third_section', 'My Third Section Title', array( $this, 'section_callback' ), 'smashing_fields' ); }

これらの3つのセクションはすべて、その3番目の引数スロットにコールバックsection_callbackが設定されています。 次に、そのコールバックに一致するメソッドを作成し、そこに「HelloWorld」をドロップすると、次のようになります。

 public function section_callback( $arguments ) { echo '

こんにちは世界

'; }

次のようなものが得られます。

同じコールバック関数を共有する3つのセクション
同じコールバックを共有する3つのセクション。

私はあなたが何を考えているか知っています、「なぜ私は私のすべてのセクションの下に同じテキストを持ちたいのですか?」 答えはおそらくあなたがそうしないだろうということです。 これは、 add_settings_section関数で少し注意が必要な場所です。 その関数のドキュメントを見ると、ページのメモの部分で、コールバック関数にフックの引数に直接相関する引数の配列が割り当てられていることがわかります。 var_dump( $arguments )に入ると、すべての引数が関数に渡されるのがわかります。

次に、コールバックに単純なスイッチを記述して、渡されたIDに基づいてテキストを変更できます。

 public function section_callback( $arguments ) { switch( $arguments['id'] ){ case 'our_first_section': echo 'This is the first description here!'; break; case 'our_second_section': echo 'This one is number two'; break; case 'our_third_section': echo 'Third time is the charm!'; break; } }

これで、セクションごとに1つの関数で変更できるカスタムテキストができました。

各セクションの下のカスタムテキスト
各セクションの下のカスタムテキスト。

もちろん、これらのセクションに一意のコールバックを指定することもできますが、このアプローチでは、コードを単一の関数に統合できます。 このアイデアは、フィールドの設定でも同じように機能します。 すべてのフィールドにコールバックを共有させ、渡した引数に基づいて正しいフィールドタイプを出力させることができます。コンストラクターメソッドにフィールドを追加しましょう。 セクションがコンストラクターにフックされた直後に、このコードを配置します。

 add_action( 'admin_init', array( $this, 'setup_fields' ) );

あなたはすでにドリルを知っているので、私はあなたに私たちの行動のコールバックを与えるだけです:

 public function setup_fields() { add_settings_field( 'our_first_field', 'Field Name', array( $this, 'field_callback' ), 'smashing_fields', 'our_first_section' ); }

この関数の引数は、sections関数の引数と似ています。 最初の引数は、フィールドの一意の識別子です。 2つ目は、フィールドの横に表示されるラベルです。 3番目の引数では、メソッドfield_callbackを呼び出していることがわかります。 そのコールバックをすぐに作成します。 4番目は使用したいオプションページです(以前の$slug )。 5番目の引数は、このフィールドを割り当てるセクションの一意の識別子です

3番目の引数のコールバックのコードは次のとおりです。

 public function field_callback( $arguments ) { echo '<input name="our_first_field" type="text" value="' . get_option( 'our_first_field' ) . '" />'; }

ここでは、フィールドの一意の識別子を名前、ID、およびget_option関数にコピーしているだけです。 新しいフィールドを添付してページがどのように表示されるかを見てみましょう。

最初のフィールドがある設定ページ。
最初のフィールドが添付された設定ページ。

素晴らしい、ページにフィールドがあります! コンテンツを追加して変更を保存してみてください。ここで待ちます…

あなたはそれをやりましたか? この時点までにすべてを実行した場合は、「 ERROR: options page not found 」などのエラーが発生するはずです。 これが発生する理由は、実際にはWordPressのセキュリティ機能です。

この機能がないと、ユーザーはHTMLにアクセスしてフィールドの名前を任意の名前に変更し、[保存]をクリックすると、指定された名前でそのオプションがデータベースに入力されます(有効な場合)。オプション名)。 これにより、ユーザーはフィールドに正しい名前を入力して[保存]をクリックするだけで、他のページ(通常はアクセスできないページでも)のオプションを変更できます。

この問題は、 register_settingという関数を追加することで解決されます。 WordPressに「ねえ、このフィールドはこのページに保存できます」と具体的に指示しない限り、WordPressはデータベースのフィールドを更新しません。 したがって、フィールドマークアップの下に、この新しい関数を追加します。 コードを追加した後のコールバックは次のようになります。

 public function field_callback( $arguments ) { echo '<input name="our_first_field" type="text" value="' . get_option( 'our_first_field' ) . '" />'; register_setting( 'smashing_fields', 'our_first_field' ); }

新しい関数の最初の引数は、フィールドを保存するオプションページ(以前の$slug )であり、2番目の引数は保存するフィールドです。 次に、フィールドを更新してみてください–うまくいきました!

おめでとう! WordPress設定APIを使用して最初のフィールドを保存しました。 では、テキストだけでなく、いくつかの異なるフィールドタイプが必要な場合はどうでしょうか。 フィールドコールバックに戻り、 $arguments変数が関数に渡されることについて話しましょう。

フィールド引数

フィールドコールバックとvar_dump( $arguments )に入ると、空の配列が取得されます。 何が得られますか? セクションのコールバックでは、セクションに関する多くの情報を取得しました。 さて、ここで何か違うことが起こっています。 add_settings_fieldのドキュメントを確認すると、関数に渡すことができる5番目の引数があります。 その変数は、コールバックの$arguments変数に直接相関します。 だから私たちはそこに新しいものを入れたいと思うでしょう。

WordPress設定ページのデフォルトフィールドの1つを見ると、デフォルトのフォーマットを取得するためにフィールドに追加できる領域がいくつかあることがわかります。 一般設定ページのタイムゾーンフィールドのスクリーンショットは次のとおりです。

WordPressのタイムゾーンフィールド
WordPressのタイムゾーンフィールド。 (拡大版を表示)

このフィールドを開始点として使用して、フィールドコールバックに渡したいデータを調べてみましょう。

  • 一意の識別子
  • フィールドのラベル(例ではタイムゾーン)
  • どのセクションに入る必要がありますか
  • フィールドのタイプ(テキスト、テキストエリア、選択など)
  • 複数のオプションがある場合は、それらが必要になります
  • フィールドタイプがプレースホルダーをサポートしている場合は、プレースホルダーかもしれません
  • ヘルパーテキスト(例のフィールドの右側)
  • 補足テキスト(例のフィールドの下)
  • たぶんデフォルトの選択があれば

このリストから、コールバックに渡すことができるフィールドと値の連想配列を設定できます。

 public function setup_fields() { $fields = array( array( 'uid' => 'our_first_field', 'label' => 'Awesome Date', 'section' => 'our_first_section', 'type' => 'text', 'options' => false, 'placeholder' => 'DD/MM/YYYY', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => '01/01/2015' ) ); foreach( $fields as $field ){ add_settings_field( $field['uid'], $field['label'], array( $this, 'field_callback' ), 'smashing_fields', $field['section'], $field ); register_setting( 'smashing_fields', $field['uid'] ); } }

したがって、ここで最初に使用するのは、作成するすべてのフィールドを保持する$fieldsという変数です。 その配列内には、各フィールドの特定のデータを保持する別の配列があります。 上記のリストと完全に一致するようにデータを設定しました。 次に、配列内の各フィールド(後で追加します)をループし、フィールドを追加して登録します。 add_settings_field関数の最後に、その特定のフィールドのデータの配列全体を追加して、コールバック関数でいくつかの処理を実行できるようにします。 ここでそのコールバック関数を見てみましょう:

 public function field_callback( $arguments ) { $value = get_option( $arguments['uid'] ); // Get the current value, if there is one if( ! $value ) { // If no value exists $value = $arguments['default']; // Set to our default } // Check which type of field we want switch( $arguments['type'] ){ case 'text': // If it is a text field printf( '<input name="%1$s" type="%2$s" placeholder="%3$s" value="%4$s" />', $arguments['uid'], $arguments['type'], $arguments['placeholder'], $value ); break; } // If there is help text if( $helper = $arguments['helper'] ){ printf( '<span class="helper"> %s</span>', $helper ); // Show it } // If there is supplemental text if( $supplimental = $arguments['supplemental'] ){ printf( '<p class="description">%s</p>', $supplimental ); // Show it } }

上記の例では、いくつかのことを行っています。 フィールドが空の場合はデフォルト値を設定し、ヘルパーと補足テキストを追加します。 ただし、コードで最も重要な部分はswitchステートメントです。 このステートメントでは、必要なフィールドタイプに基づいて引数がどのように処理されるかについて概説します。

たとえば、テキストフィールドがある場合、複数のオプションを用意する必要はありません。 ただし、 <select>ドロップダウンには、正しく機能するためのオプションが必要です。 すでにテキストタイプが設定されているので、このコードを実行して、何が得られるかを見てみましょう。

プレースホルダーを含めて入力されたフィールド
プレースホルダーテキストを含むフィールドに入力しました。 (拡大版を表示)

プラグイン設定ページをロードすると、この画像の一番上のフィールドが表示されます。 下部は、フィールド(つまりプレースホルダー)からコンテンツを削除した場合に表示されるものです。 フィールド配列からhelper引数またはsupplimental引数を削除すると、設定ページに表示されなくなります。 section引数を変更して、セクション内のフィールドの配置を移動することもできます。

OK、テキストフィールドがあります。 より複雑なフィールドタイプはどうですか? switchステートメントをもう一度見て、テキスト領域と単一選択のオプションを追加しましょう。

 switch( $arguments['type'] ){ case 'text': // If it is a text field printf( '<input name="%1$s" type="%2$s" placeholder="%3$s" value="%4$s" />', $arguments['uid'], $arguments['type'], $arguments['placeholder'], $value ); break; case 'textarea': // If it is a textarea printf( '<textarea name="%1$s" placeholder="%2$s" rows="5" cols="50">%3$s</textarea>', $arguments['uid'], $arguments['placeholder'], $value ); break; case 'select': // If it is a select dropdown if( ! empty ( $arguments['options'] ) && is_array( $arguments['options'] ) ){ $options_markup = '; foreach( $arguments['options'] as $key => $label ){ $options_markup .= sprintf( '<option value="%s" %s>%s</option>', $key, selected( $value, $key, false ), $label ); } printf( '<select name="%1$s">%2$s</select>', $arguments['uid'], $options_markup ); } break; }

上記のコードでは、各フィールドタイプの間にいくつかの違いがあります。 テキスト領域は機能的には通常のテキストフィールドと似ていますが、異なるマークアップが必要です。 オプションがあるため、選択ドロップダウンはまったく別の動物です。 オプションをループして、値、選択した状態、およびラベルを設定する必要があります。 したがって、マークアップは大幅に異なります。

コールバック関数を更新したので、フィールドデータがどのように変更されたかを見てみましょう。

 $fields = array( array( 'uid' => 'our_first_field', 'label' => 'Awesome Date', 'section' => 'our_first_section', 'type' => 'text', 'options' => false, 'placeholder' => 'DD/MM/YYYY', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => '01/01/2015' ), array( 'uid' => 'our_second_field', 'label' => 'Awesome Date', 'section' => 'our_first_section', 'type' => 'textarea', 'options' => false, 'placeholder' => 'DD/MM/YYYY', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => '01/01/2015' ), array( 'uid' => 'our_third_field', 'label' => 'Awesome Select', 'section' => 'our_first_section', 'type' => 'select', 'options' => array( 'yes' => 'Yeppers', 'no' => 'No way dude!', 'maybe' => 'Meh, whatever.' ), 'placeholder' => 'Text goes here', 'helper' => 'Does this help?', 'supplemental' => 'I am underneath!', 'default' => 'maybe' ) );

これが3つのフィールドで、それぞれがプラグインで異なるフィールドタイプを使用しています。 私たちがすでに行った最初のもの。 2つ目は、新しいtextareaフィールドです。 配列(UIDを除く)で同じパラメーターを渡すことができますが、タイプを変更するだけで、代わりにtextareaを取得します。 この配列の最後のフィールドは、選択ドロップダウンです。 ここでの主な更新は、options配列の追加です。 HTMLオプション値として配列キーとラベルを使用して単純な連想配列を追加します。 この配列を使用すると、フィールドは次のようになります。

フィールドに入力した後の設定ページ
フィールドのある設定ページ。 (拡大版を表示)

ほぼ完了しました!

これで、プラグイン設定ページが機能するようになりました。 ページのセクション、オプション、すべてのコールバックを設定し、フィールドを登録しました。 残っているのは、他の場所で設定値を取得することだけです。 信じられないかもしれませんが、私たちはすでにこれを行っています。 フィールドコールバックの上部に、データベース値をチェックしていることがわかります。

 $value = get_option( $arguments['uid'] );

プラグイン(またはテーマ)で同じコードを使用して、 uidを関数に渡すだけです。 したがって、 our_first_fieldの値を取得したい場合は、次のように記述します。

 get_option('our_first_field')

ねえプレスト! 素晴らしいプラグインと素晴らしい設定があります! 明らかに、いくつかのフィールドタイプを設定しただけですが、このアプローチのコードリポジトリにさらに追加しました(具体的には、テキストフィールド、パスワード、数字、テキストエリア、選択ドロップダウン、複数選択、ラジオボタン、チェックボックス)。

アプローチ2:カスタムフォームとハンドラーの設定

以前は、このアプローチが設定ページを追加する唯一の方法でした。 WordPress 2.7プラグイン以前は、作成者は独自のカスタムフォームとハンドラーを作成する必要がありました。 これは明らかに、プラグイン間の多くのバグと不整合につながりました。 このアプローチはやや非推奨ですが、それでも実行可能なオプションである場合があります。

長所

  • フォームをカスタムハンドラーとリモートハンドラーに送信できます
  • 組み込みの設定API制限の一部をバイパスできます

短所

  • 互換性は開発者が維持する必要があります
  • 手動で消毒および検証する必要があります

このアプローチはいつ使用する必要がありますか?

カスタムハンドラーまたは高度にカスタムなインターフェイスが絶対に必要な場合は、このアプローチを使用してください。 ほとんどの場合、アプローチ1で問題を解決できますが、この方法を使用すると、検証と処理の柔軟性が高まります。

入門

詳細に入る前に、カスタムハンドラーを使用するシナリオを考え出す必要があります。 わかりやすくするために、ユーザー名とメールアドレスを確認するフォームを作成しましょう。 データベースまたはリモートサーバーからデータをプルすることもできます。 この場合、チェックするための有効なユーザー名と電子メールアドレスを含む配列を設定します。 次に、ユーザーが入力したフィールド値を保存し、データベースに保存します。

フォームの作成

前に述べたように、「プラグインと設定ページの作成」で行ったのと同じ手順に従います。 このアプローチでは、静的HTMLマークアップを使用してフィールドを設定します。 次のように、 plugin_settings_page_content関数からのコールバックにこのコードを追加します。

 public function plugin_settings_page_content() { ?> <div class="wrap"> <h2>My Awesome Settings Page</h2> <form method="POST"> <table class="form-table"> <tbody> <tr> <th><label for="username">Username</label></th> <td><input name="username" type="text" value="" class="regular-text" /></td> </tr> <tr> <th><label for="email">Email Address</label></th> <td><input name="email" type="text" value="" class="regular-text" /></td> </tr> </tbody> </table> <p class="submit"> <input type="submit" name="submit" class="button button-primary" value="Check My Info!"> </p> </form> </div> <?php }

上記のように、フィールドに静的HTMLを追加しているだけです。 コアのWordPress設定ページからマークアップを複製しています。 また、デフォルトのoptions.phpハンドラーではなく、現在のページにフォームを送信するように、フォームアクションを省略しています。

カスタムハンドラーを作成する前に、いくつかの簡単なセキュリティ機能を導入しましょう。 私たちが最初にすべきことは、私たちのフォームにナンスを入れることです。 Noncesは、ユーザーのなりすまし攻撃やリプレイ攻撃に似た、クロスサイトリクエストフォージェリの試みから保護します。 ナンスをHTMLに入れましょう:

 <form method="POST"> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">

wp_nonce_fieldは、フォームにいくつかの非表示フィールドを追加します。 ノンスとリファラー。 ハンドラーコードを実行すると、ナンスに戻ります。

次に、フォームが更新されたことを検出するフィールドを追加する必要があります。 これを行うには、フォームの上部に非表示のフィールドを追加するだけです。

 <form method="POST"> <input type="hidden" name="updated" value="true" /> <?php wp_nonce_field( 'awesome_update', 'awesome_form' ); ?> <table class="form-table">

これで、ページの上部にコードのスニペットを配置して、フォームが送信されたことを検出し、カスタムハンドラーに送信できます。

 public function plugin_settings_page_content() { if( $_POST['updated'] === 'true' ){ $this->handle_form(); } ?> <div class="wrap"> <h2>My Awesome Settings Page</h2>

ここでは、非表示のupdatedフィールドが送信されたかどうかを確認しているだけです。送信されている場合は、プラグインでhandle_formというメソッドを呼び出します。 ここから、カスタムハンドラーの作成を開始できます。

ハンドラーの作成

フォームデータを実際に管理する前に、ハンドラーでチェックする必要があることがいくつかあります。 まず、ナンスが存在し、有効であるかどうかを確認する必要があります。

 public function handle_form() { if( ! isset( $_POST['awesome_form'] ) || ! wp_verify_nonce( $_POST['awesome_form'], 'awesome_update' ) ){ ?> <div class="error"> <p>Sorry, your nonce was not correct. Please try again.</p> </div> <?php exit; } else { // Handle our form data } }

上記のコードは、ナンスが正しいことを確認します。 無効な場合は、フォームが更新されなかった理由に関するメッセージをユーザーに提供します。 ナンスが存在し、正しい場合は、フォームを処理できます。 ここで、フォームハンドラーのコードを記述しましょう(このコードは、上記のスニペットのコメントを置き換えます)。

 $valid_usernames = array( 'admin', 'matthew' ); $valid_emails = array( '[email protected]', '[email protected]' ); $username = sanitize_text_field( $_POST['username'] ); $email = sanitize_email( $_POST['email'] ); if( in_array( $username, $valid_usernames ) && in_array( $email, $valid_emails ) ){ update_option( 'awesome_username', $username ); update_option( 'awesome_email', $email );?> <div class="updated"> <p>Your fields were saved!</p> </div> <?php } else { ?> <div class="error"> <p>Your username or email were invalid.</p> </div> <?php }

このセクションのコードを見ていきましょう。 最初の数行は、チェックする有効なユーザー名/メールの配列です。 これらの配列値は、どこからでも入力できます。

次の2行は、ユーザーがフォームに入力した値です。 WordPressが提供する組み込みのサニタイズ機能を使用しています。 この手順は、Webフォームのいくつかの脆弱性を回避するために重要です。 次に、ユーザーから提供された値が許容値の配列に含まれているかどうかを確認しています。 そうである場合は、データベースのフォームオプションを更新します。 この手順は、カスタムストレージメカニズムに置き換えることもできます。 また、フィールドが保存されたことを示すメッセージをユーザーに提供しています。 ユーザーの入力が無効な場合は、そのように通知します。

最後に行う必要があるのは、入力された後にフォームに保存されたフィールドを表示することです。 プラグインの他の場所でこれらのフィールドを取得するのと同じ方法で、 get_option関数を使用してこれを行います。 正しいコードを追加した後のフィールドは次のとおりです。

 <tr> <th><label for="username">Username</label></th> <td><input name="username" type="text" value="<?php echo get_option('awesome_username'); ?>" class="regular-text" /></td> </tr> <tr> <th><label for="email">Email Address</label></th> <td><input name="email" type="text" value="<?php echo get_option('awesome_email'); ?>" class="regular-text" /></td> </tr>

これで、フォームをテストする準備が整いました。 ユーザー名adminとメールアドレス[email protected]を入力してみてください。 フォームに次の情報が表示されます。

正しい値を入力した後に保存されたフィールド
正しい値を入力した後に保存されたフィールド。 (拡大版を表示)

いずれかのフィールドを無効な値に設定しようとすると、エラーメッセージが表示され、カスタムハンドラーが原因でフィールドが更新されないはずです。

2番目のアプローチは以上です。 これで、プラグインフィールドを管理するためのカスタムフォームとハンドラーが設定されました。 このアプローチの完成したコードは、この記事のリポジトリにあります。 それでは、最後のアプローチに移りましょう。

アプローチ3:プラグインへのACF(高度なカスタムフィールド)の統合

Elliot CondonのACFをまだ使用していない場合は、紹介させてください。 ACFはWordPressの素晴らしいフィールドマネージャーです。 それについての最もよいことの1つはフィールド構成インターフェースです。 これにより、WordPress内のさまざまなページ(投稿、ページ、ユーザー、分類法、さらには独自の統合オプションページなど)のフィールドを簡単にスピンアップできます。 「他の人のプラグインを自分のプラグインに統合することはできません。それは日陰です!」と思うかもしれません。 しかし、コンドン氏は彼の仲間の開発者の窮状を理解しており、彼のプラグインでこれを計画しています。 このトピックに関する彼のドキュメントを見ることができますが、ここでその一部を言い換えます。 ルールを見てみましょう。

  1. まず、無料のプラグインを配布する場合は、無料バージョンのACFを使用する必要があります。 これは、無料のプラグインからPROバージョンを入手できないようにするためです。これはクールではありません。 プレミアムプラグインとテーマでPROバージョンを問題なく使用できます。必ず、開発者ライセンスを購入してください。
  2. 次に、ACFの著作権情報を変更しないでください。 男にクレジットを与えてください!
  3. 最後に、プラグインと一緒にライセンスキーを配布しないでください。

さて、このアプローチの長所と短所:

長所

  • テーマやプラグインに非常に簡単に統合できます
  • ACFの一部である高度なフィールドを利用できます
  • コードとセキュリティの更新はACFチームによって管理されます
  • ACFには、行き詰まった場合の優れたアドオンとサポートがあります
  • フィールド構成UIにより、フィールドの構成は非常に簡単です。

短所

  • マークアップへのアクセスが制限されています
  • プラグインまたはテーマの依存関係を作成します
  • ACFを最新の状態に保つには、プラグイン/テーマファイルでACFを最新の状態に保つ必要があります(詳細は以下を参照)。

このアプローチはいつ使用する必要がありますか?

高度な設定インターフェイスを非常に迅速に構築したい場合で、ルックアンドフィールをカスタマイズする必要はありません。

入門

このアプローチでは、無料バージョンのACFのオプションページを設定する方法を説明します。 PROバージョンの設定に関するガイドを表示するには、ACFのドキュメントを確認してください。 To get started we will be adding ACF to our plugin directory. First, download the latest version of ACF and unzip its contents. In your plugin directory create a (拡大版を表示)

Again, we will follow the steps we did in “Creating Our Plugin And Settings Page”. Before we get into that, though, we should include ACF in our plugin.

Include ACF In Your Plugin

It's actually pretty easy to include ACF in your plugin – there are only three steps. First we have to include the main ACF file with PHP. Add the following code to the bottom of our constructor function:

 include_once( plugin_dir_path( __FILE__ ) . 'vendor/advanced-custom-fields/acf.php' );

If you refresh the admin you should see a new menu item titled Custom Fields . Before we go into that page and start setting up our fields we need to update a couple of paths in ACF. We need to tell ACF to look for its front-end assets and file includes in our plugin directory instead of its normal place. Add these two hooks to your constructor:

 add_filter( 'acf/settings/path', array( $this, 'update_acf_settings_path' ) ); add_filter( 'acf/settings/dir', array( $this, 'update_acf_settings_dir' ) );

And the callbacks for those hooks:

 public function update_acf_settings_path( $path ) { $path = plugin_dir_path( __FILE__ ) . 'vendor/advanced-custom-fields/'; return $path; } public function update_acf_settings_dir( $dir ) { $dir = plugin_dir_url( __FILE__ ) . 'vendor/advanced-custom-fields/'; return $dir; }

The first callback updates the include paths for the PHP files within the ACF plugin. The second updates the URIs for the ACF assets. Now we can set up our fields.

Configuring Your Fields

Now comes the fun part: the ACF field configuration UI. Add a title and any fields you'd like in your form. There is a great walkthrough of what everything on this page does in the ACF documentation. Here's how I have set up mine:

ACF fields configured
My ACF fields in the configuration UI. (拡大版を表示)

Once you are ready hit the Publish button on the right and your fields will be saved. Now we have to get the fields we set up into our plugin. Right now they only exist in the database. On the left-hand navigation, click the Tools item. On the new page, select the field group we just created and hit Generate Export Code . This will create a chunk of PHP code that we can now include in our plugin.

To add the options, we need to add a method call to our constructor. Add this line to the end of your constructor after our ACF include:

 $this->setup_options();

Then we can create the method that will wrap our options:

 public function setup_options() { if( function_exists( 'register_field_group' ) ) { register_field_group(array ( 'id' => 'acf_awesome-options', 'title' => 'Awesome Options', 'fields' => array ( array ( 'key' => 'field_562dc35316a0f', 'label' => 'Awesome Name', 'name' => 'awesome_name', 'type' => 'text', 'default_value' => ', 'placeholder' => ', 'prepend' => ', 'append' => ', 'formatting' => 'html', 'maxlength' => ', ), array ( 'key' => 'field_562dc9affedd6', 'label' => 'Awesome Date', 'name' => 'awesome_date', 'type' => 'date_picker', 'date_format' => 'yymmdd', 'display_format' => 'dd/mm/yy', 'first_day' => 1, ), array ( 'key' => 'field_562dc9bffedd7', 'label' => 'Awesome WYSIWYG', 'name' => 'awesome_wysiwyg', 'type' => 'wysiwyg', 'default_value' => ', 'toolbar' => 'full', 'media_upload' => 'yes', ), ), 'location' => array ( array ( array ( 'param' => 'options_page', 'operator' => '==', 'value' => 'smashing_fields', ), ), ), 'menu_order' => 0, 'position' => 'normal', 'style' => 'default', 'label_placement' => 'top', 'instruction_placement' => 'label', 'hide_on_screen' => ', 'active' => 1, 'description' => ', )); } }

Now that we have our fields ready to go, we can add them to the settings page.

Modifying The Settings Page Code

To add the fields we just created to the page we will need to update our plugin_settings_page_content method.

Previously, we set up the form tag for our page. In this case we will let ACF do that part for us. Here is what our updated function should look like:

public function plugin_settings_page_content() { do_action('acf/input/admin_head'); // Add ACF admin head hooks do_action('acf/input/admin_enqueue_scripts'); // Add ACF scripts $options = array( 'id' => 'acf-form', 'post_id' => 'options', 'new_post' => false, 'field_groups' => array( 'acf_awesome-options' ), 'return' => admin_url('admin.php?page=smashing_fields'), 'submit_value' => 'Update', ); acf_form( $options ); }

関数の最初の2行は、設定フィールドに必要なスクリプトとスタイルを追加しています。 その後、フォームのオプションを構成します。 field_groups引数の値が、 register_field_group関数のIDと一致していることに気付くかもしれません。 他の構成パラメーターを確認するには、 acf_formのドキュメントを参照してください。 関数の最後の行は、実際にフォームをレンダリングします。

ここで設定ページを読み込もうとすると、実際にページが壊れていることがわかります。 これは、ACFがJavaScriptのいくつかの変数をローカライズする必要があるためです。 これを行うには、コンストラクターに別のフックを追加する必要があります。

 add_action( 'admin_init', array( $this, 'add_acf_variables' ) );

次に、コールバックを設定する必要があります。

 public function add_acf_variables() { acf_form_head(); }

コンテンツを追加して保存してみると、他の2つのアプローチと同じように機能するはずです。 これは私たちのページがどのように見えるべきかです:

完成したACFフォーム
記入済みのACFフォーム。 (拡大版を表示)

対処する必要のあるクリーンアップ項目がいくつかあります。

  • プラグインにACFを使用しているという事実を隠したい場合があります。 この場合、[カスタムフィールド]メニュー項目を非表示にする必要があります。 これを行うには、このスニペットをコンストラクター関数に追加します。

     add_filter( 'acf/settings/show_admin', '__return_false' );
  • フィールドグループのデータベースバージョンを削除する必要があります。 カスタムフィールドセクションに移動して、ゴミ箱ボタンを押すだけです。 この手順は、プラグインを作成した環境にのみ影響するためオプションですが、同じ環境でプラグインをテストしている場合は問題が発生する可能性があります。

プラグイン内でのACFフィールドの使用

作成したACFフィールドを取得するには、デフォルトのget_field関数を使用する必要があります。 最初のオプションはフィールドの一意のIDであり、2番目の引数は'option'に設定されている必要があります。 AwesomeDateフィールドを取得する方法は次のとおりです。

 get_field( 'awesome_date', 'option' )

以上です。 これで、ACF設定を使用してプラグインがセットアップされました。 このアプローチのコードは、リポジトリで表示できます。

結論

これで、プラグインを構成可能にする3つの方法ができました。 これらのメソッドを使用して作成できるプラグインについてお聞かせください。 繰り返しになりますが、これらの各アプローチのコードを格納するリポジトリを設定しました。 気軽にフォークして、自分のニーズに合わせてカスタマイズしてください。

これらのアプローチに対する私の個人的な好みについては、アプローチ1に傾倒する傾向があります。プラグインの依存関係をできるだけ少なくし、マークアップをカスタマイズしてカスタムプロジェクトの設定ページのテーマを設定できます。 ラピッドプロトタイピング、または非常に高度なフィールドを設定する必要があるプロジェクトでは、ACFを使用しますが、プラグインの更新の管理にある程度の複雑さが加わります。

また、ScottClarkによるFieldsAPIの提案についても言及する価値があります。 現在も作業中ですが、APIを使用すると、プラグインとテーマの開発者は、カスタマイザーAPIと同じインターフェイスを使用して、管理パネルの他の領域に設定フィールドを作成できます。

ACFの代替案

以下のコメントで指摘されているように、ACFアプローチに類似した他のオプションを開発者に提供するために、さまざまな機能を提供する可能性のあるいくつかの代替案を確認できます。 あなたがもっと持っているならば、下のコメントでそれらを提出してください! ここでは、それらは特定の順序ではありません。

  • WebDevStudiosによるCMB2
  • Tran Ngoc Tuan Anh(Rilwis)によるメタボックス