Settings APIの利点は何ですか?


13

私がWordPressで仕事をすることはほとんどない、と言ってこれを序文させてください。実際、WordPressでサイトを最後にやったのは2.2の間に戻ってきました。昨日、私はすべてをかなり混乱させ、基本的なメニュープラグインを機能させるために、ここでいくつかの質問をしました。

プラグインが完全に機能し、期待どおりに動作するようになったので、設定APIを使用するなど、機能と互換性を追加するために、あちこちで小さな変更を加えることにしました。しかし、このAPIのチュートリアルを読んで非常に短い時間で、私はかなり混乱しました。次に、この混乱を深め、サンプルを実装しようとしました。 。

何か間違ったことをしていない限り、Settings APIを使用するために理解していることから、PER SETTINGという新しい関数を作成する必要があります。これは、平均的なプラグインでは3〜5個の関数、より高度なプラグインでは最大数百個の関数を意味します。すべての適用可能な$_POST変数を配列に簡単にインポートし、混乱を避けることができる場合に、この多くの関数を記述して(そしてそれらを混乱させないように命名システムを開発するのは)馬鹿げているようです。

たぶん私は昔ながらですが、そこから得るものがない限り、私が書いているコードの量を3倍や4倍にする理由はわかりません。Settings APIを追加する前にオプションを管理する方法は次のとおりです。

    function __construct() {
        /* constructor stuff */
        $this->options = $this->db_options = get_option( 'de-menu-options' );
        if( $this->options === false ){
            $this->options = $this->defaults;
        }
        if (is_admin()) {
            add_action('admin_menu', array(&$this, 'admin_menu'));
        }   
        /* more stuff */

        // When WordPress shuts down we store changes to options
        add_action('shutdown', array(&$this, 'update'));
    }

    public function admin_menu() {
        add_options_page('DE Menu Options', 'DE Menu', 'manage_options', 'de-menu-options', array(&$this, 'options'));
        add_option('de-menu-options', $this->options);
    }

    public function options() {
        if (!current_user_can('manage_options')) {
            wp_die( __('You do not have sufficient permissions to access this page.') );
        }
        if ( !empty($_POST) && check_admin_referer('de-menu-options') ) {
            // These options are saved to the database at shutdown
            $this->options = array(
                "columns" => $_POST["de-menu-columns"],
                "maintenance" => $_POST["de-menu-maintenance"]
            );
            echo 'DE Menu options saved';
        }
?>

<div class="wrap">
    <h2>DE Menu Plugin</h2>
    <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
        <?php settings_fields('de-menu-options'); ?>
        <input type="checkbox" name="de-menu-maintenance" />
        <label for="de-menu-columns">Columns:</label>
        <input type="text" name="de-menu-columns" value="<?php echo $this->options['columns']; ?>" />
        <p class="submit">
        <input type="submit" name="de-menu-submit" value="Update Options »" />
        </p>
    </form>
</div>
<?php
    }

    function update() {
        // By storing all changes at the end we avoid multiple database calls
        $diff = array_diff( $this->options, $this->db_options );
        if( !empty( $diff )  ){
            update_option('de-menu-options', $this->options);
        }
    }

設定APIを使用すると、次のようになります。

    function __construct() {
        /* constructor stuff */
        // Do I load options? Will they be loaded for me? Who knows?
        if (is_admin()) {
            add_action('admin_menu', array(&$this, 'admin_menu'));
            add_action('admin_init', array(&$this, 'admin_init'));
        }   
        /* more stuff */
        // Settings API should update options for me... I think
    }

    public function admin_menu() {
        add_options_page('DE Menu Options', 'DE Menu', 'manage_options', 'de-menu-options', array(&$this, 'options'));
        add_option('de-menu-options', $this->options);
    }

    public function admin_init() {
        register_setting('de-menu-options','de-menu-options',array(&$this,'validate'));
        add_settings_section('de-menu-main-options', 'Main Settings', 'options_section', 'de-menu-options');
        add_settings_field('de-menu-maintenance', 'Maintenance Mode', array(&$this,'options_maintenance'), 'de-menu-options', 'de-menu-main-options');
        add_settings_field('de-menu-columns', 'Columns', array(&$this,'options_columns'), 'de-menu-options', 'de-menu-main-options');
    }

    public function options() {
        if (!current_user_can('manage_options')) {
            wp_die( __('You do not have sufficient permissions to access this page.') );
        }
        if ( !empty($_POST) && check_admin_referer('de-menu-options') ) {
            // These options are saved to the database at shutdown
            $this->options = array(
                "columns" => $_POST["de-menu-columns"],
                "maintenance" => $_POST["de-menu-maintenance"]
            );
            echo 'DE Menu options saved';
        }
?>

<div class="wrap">
    <h2>DE Menu Plugin</h2>
    <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
        <?php settings_fields('de-menu-options'); ?>
        <?php do_settings_sections('de-menu-options'); ?>
        <p class="submit">
        <input type="submit" name="de-menu-submit" value="Update Options »" />
        </p>
    </form>
</div>
<?php
    }

    public function options_section() {
        echo '<p>' . __('Main description of this section here.','de-menu-lang') . '</p>';
    }

    public function options_maintenance() {
        echo "<input id='de-menu-maintenance' name='options[maintenance]' type='checkbox' />";
    }

    public function options_columns() {
        echo "<input id='de-menu-columns' name='options[columns]' type='checkbox' value=".$this->options['columns']."/>";
    }

    function validate($options) {
        return $options; // I guess?
    }

おそらく、2つのオプションだけでコードがすでに長くなっていることは、スクロールバーから痛々しいほど明らかです。私がやっていることを完全に理解していないことはコメントからも同様に明らかです。次に、これらすべてを実現するために、5つの新しい関数を使用する(および1つだけ削除する)という問題があります。

それで、私はこの余分な仕事のすべてからどんな利点を得ていますか?


そのような場合には使用しないでください。プラグイン/テーマ内に3〜4個のオプションが必要なPHP初心者を対象としています。これは、実装されるべきではなかった「機能」の1つです...これは、基本的に別のAPIのAPIです:)
onetrickpony

3
私は書くすべてに設定APIを使用していますが、それはあなたがそれをどのように使用するかに依存します。add_settings_sectionそしてadd_settings_field、を使用せずにAPIを使用できることに注意してください。
t31os

1
t3losと同じことを行います。設定自体を登録し、設定ページでHTMLのフォームにコーディングするだけです。これを本当に簡単に行い、後でコードを保持したい場合は、YoastのWordPress SEOプラグインをご覧ください。
chrisguitarguy

回答:


8

私の見解では、Settings APIの主な目的と利点は構造です。

複雑な設定を維持するのに役立ちます。

  • 秩序ある(登録とセクションの論理)。
  • セキュア(ノンス、検証コールバック);
  • 拡張可能(別のページにフックするか、フックできるようにする)。

このような構造的なオーバーヘッドと同様に、より複雑なユースケースに役立つだけでなく、単純ではないユースケースにも役立ちます。

したがって、Settings APIを使用せずに何でも実装できます。問題は、信頼性が高く、安全で、拡張可能な方法でそれを達成できるかどうかです。


私はついに、このチュートリアルalisothegeek.com/2011/01/wordpress-settings-api-tutorial-1のヘルプと、switchステートメントとヘルパー関数の助けを借りて、設定ページが機能するようになりました。私のコードで(2つのテスト設定から合計15〜20の設定に移行する予定なので、これは素晴らしいことです)。
-stevendesu

1
@steven_desuうん、実行中の冗談は、Settings APIを使用するすべての人がそのためのフレームワークを書くということです。:)カップルヘルパー関数はほとんど避けられません。また、Settings APIは最終的なものとは見なされておらず、将来的に改善するための(あいまいな)計画があります(3.3計画のコンテキストで言及されたと思います)。
11

1
私は確かにそれが改善されることを願っています。正直、Settings APIには何の利点もありませんが、私が今楽しんでいるすべての利点は、私が借りたフレームワークの結果です。すべてのフォーム要素が同じ外観で動的に生成されるようになりました...しかし、それはSettings APIではありません。デフォルト設定と登録設定が同じ定義で処理されるのが好きですが、それは設定APIではありません。私はjQueryがフォームをきれいにするだけでなく、段階的に強化されることを気に入っています
しかし

5

コールバックを適切に使用すれば、すべての冗長コードは必要ありません。完全にスケーラブルな方法で、設定APIを実装する方法を次に示します

利点(特に):

  • Settings APIは、信頼できないユーザーデータのサニタイズを強制します。
  • Settings APIは、オプションをオプション配列として強制的に登録し、各オプションの個別のDBエントリではなく、単一のwp_options DBエントリを作成します。
  • Settings APIは、設定フォームのセキュリティ強化を促進します
  • 設定APIは、コア管理UIと一貫した管理UIを促進し、より良いUXをもたらします

それで、本質的に私はすでに助けなしで従っていたセキュリティと審美的な基準を強制しますか?ただし、リンクしたチュートリアルを読みます。フォームを手動でコーディングするのと同じくらい簡単に(またはより簡単に)設定APIを作成できる場合は、この回答を受け入れます
-stevendesu

あなたは、ソースコードを使用すると、実装の機能を指摘していることを認識しているoenology_get_settings_by_tab()oenology_get_default_options、これまでそれらを最初に定義することなく?209行のコード(コメントと空白行を削除した後)で十分だと思いましたが、これらの関数が定義されるとさらに長くなります... 4つのオプションについては?
-stevendesu

それらは他の場所で定義されています。これoenology_get_settings_by_tab()は、あなたがやっていることにはあまり関係ありません。しかし、何らかの方法でユーザー入力を検証/サニタイズする必要があるのと同じように、フォームフィールドマークアップをどこかで定義する必要あります。
チップベネット

0

これを投稿してくれてありがとう、私はまったく同じことを疑問に思っていました。多くの機能。

それらを減らすために、オプションを配列として保存できます。Wordpressはデータをシリアル化します。これにより、コード(または機能)は節約されますが、データが悪化します。たとえば、テーブルの並べ替え、編集、エクスポートなどを行う場合、テーブルにはこれらのシリアル化された値が含まれます。一方、プラグインはオプションテーブルに追加するエントリが少なく、クリーンアップが簡単です。

コードを再作成します。いくつかのメモ:

  • 私の例は、単純なオプション(de_w、de_h)と配列オプション(de_width_height)の両方を示しています。
  • 常にユーザー入力をサニタイズします。例では整数を使用しました。これは、整数を簡単に無害化できるためです。
  • Settings APIを使用する場合、$ _ POST、nonce、check_admin_referer()、update_option()などは必要ありません。
  • 保存は、シャットダウン時ではなく、次のページの読み込み時に行われます。次に、WPはページにリダイレクトします。そのため、デバッグするには、出力を出力し、検証関数の1つでwp_die()を呼び出します。
  • フォームアクションは常に「options.php」です。これがSettings APIの仕組みです。他のものは使用しないでください。必要に応じて、admin_url( 'options.php')を使用できます。
  • WPは、保存メッセージを印刷します。
  • ここには含まれていない拡張機能:<label>アクセシビリティのための使用。add_settings_error()、settings_error()を使用して、メッセージとエラーを処理します。多くの場合、それがオプションごとに個別の検証機能を持つ唯一の理由です。以下に示すように、validate_w()とvalidate_h()は1つの関数になります。メッセージングを抽象化することを検討しましたが、検証コールバックに十分な情報がありません。あなたが取り組んでいる分野が好きです。
  • 検証コールバック関数は、Settings APIから生の$ _POST値を取得します。パラメーターに$ rawという名前を付けるのが好きです。配列オプションの場合、魔法のような配列を取得します。
  • 編集:$ thisは&$ thisよりも優れています。

コード:

<?php
$foo= new de_Foo();
class de_Foo {
function __construct() {
    if (is_admin()) {
        add_action('admin_menu', array($this, 'admin_menu'));
        add_action('admin_init', array($this, 'admin_init'));
    } 
}
public function admin_menu() {
    add_options_page(
       'DE Menu Options',
       'DE Menu',
       'manage_options',
       'de-menu-options',
       array($this,'xoxptions')
    );
    // add_option('de-menu-options', $this->options);
}
public function admin_init() {
 register_setting(
      'de-menu-settings-group',
      'de_w',
      array($this, 'validate_w')
 );
 register_setting(
      'de-menu-settings-group',
      'de_h',
      array($this, 'validate_h')
 );
 register_setting(
      'de-menu-settings-group',
      'de_width_height',
      array($this, 'validate_width_height')
 );
 add_settings_section(
      'de-menu-settings-section-size',
      'Size',
      array($this, 'settings_section_size_render'),
      'de-menu-options'
 );
 add_settings_field(
      'de_w',
      'W',
      array($this, 'w_render'),
      'de-menu-options',
      'de-menu-settings-section-size'
 );
 add_settings_field(
      'de_h',
      'H',
      array($this, 'h_render'),
      'de-menu-options',
      'de-menu-settings-section-size'
 );
 add_settings_field(
      'de_width_height',
      'Width / Height',
      array($this, 'width_height_render'),
      'de-menu-options',
      'de-menu-settings-section-size'
 );
}
public function options() {
    if (!current_user_can('manage_options')) {
        wp_die( __('You do not have sufficient permissions to access this page.') );
    }
////////////////////////////
// no no no
////////////////////////////
//         if ( !empty($_POST) && check_admin_referer('de-menu-options') ) {
//             // These options are saved to the database at shutdown
//             $this->options = array(
//                 "columns" => $_POST["de-menu-columns"],
//                 "maintenance" => $_POST["de-menu-maintenance"]
//             );
//             echo 'DE Menu options saved';
//         }
////////////////////////////
?>
<div class="wrap">
<h2>DE Menu Plugin</h2>
<form method="post" action="<?php echo admin_url('options.php'); ?>">
    <?php settings_fields('de-menu-settings-group'); ?>
    <?php do_settings_sections('de-menu-options'); ?>
    <p class="submit">
    <input type="submit" name="de-menu-submit" value="Update Options" />
    </p>
</form>
</div>
<?php
}
public function settings_section_size_render() {
    echo '<p>' . __('Main description of this section here.','de-menu-lang') . '</p>';
}
public function w_render() {
 $w= esc_attr( get_option('de_w') );
 echo "<p><input name='de_w' value='$w'></p>\n";
}
public function h_render() {
 $h= esc_attr( get_option('de_h') );
 echo "<p><input name='de_h' value='$h'></p>\n";
}
public function width_height_render() {
 $width_height= get_option('de_width_height', array());
 $width= esc_attr( @$width_height['width'] );
 $height= esc_attr( @$width_height['height'] );
 echo "<p>Width: <input name='de_width_height[width]' value='$width'></p>\n";
 echo "<p>Height: <input name='de_width_height[height]' value='$height'></p>\n";
}
function validate_w($raw) {
 return (int)$raw;
}
function validate_h($raw) {
 return (int)$raw;
}
function validate_width_height($raw) {
 is_array($raw) or $raw= array();
 $result= array();
 $result['width']= (int)@$raw['width'];
 $result['height']= (int)@$raw['height'];
 return $result;
}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.