配列を使用した設定APIの例


32

私はWrox WordPressプラグイン開発ブックを新しいプラグインの使用を開始するための主要なリファレンスとして使用しています。すべての設定は1つの配列として保存できることを理解していますが、この例では、 Webでの検索は、例ごとに非常に異なるようです。Konstantinの投稿の後半で私は親しくなりましたが、複数のフィールドを持つより完全な例を見てみたいです。

回答:


32

簡単な答え:name属性値はschemaを使用する必要がありますoption_name[array_key]。したがって、使用するときは…

<input name="option_name[key1]">
<input name="option_name[key2]">

…検証関数のオプション値として配列を取得します。

array (
    'key1' => 'some value',
    'key2' => 'some other value'
)

PHPはこれを行いますが、これはWordPressの機能ではありません。:)

設定APIでそれを機能させるにはどうすればよいですか?

たとえば、このオプションページが必要な場合、すべての値を1つのオプションに格納し、1つの関数で検証する必要があります。

ここに画像の説明を入力してください

オプションページ

フックadmin_menuと2つの関数が必要です。1つはページを登録し、もう1つは出力をレンダリングします。

add_action( 'admin_menu', 't5_sae_add_options_page' );

function t5_sae_add_options_page()
{
    add_options_page(
        'T5 Settings API Example', // $page_title,
        'T5 SAE',                  // $menu_title,
        'manage_options',          // $capability,
        't5_sae_slug',             // $menu_slug
        't5_sae_render_page'       // Callback
    );
}

function t5_sae_render_page()
{
    ?>
    <div class="wrap">
        <h2><?php print $GLOBALS['title']; ?></h2>
        <form action="options.php" method="POST">
            <?php 
            settings_fields( 'plugin:t5_sae_option_group' );
            do_settings_sections( 't5_sae_slug' ); 
            submit_button(); 
            ?>
        </form>
    </div>
    <?php
}

フォームはであるaction必要がありますoptions.php。そうでない場合、検証は呼び出されません。PHPのソース(wp-admin/options-permalink.php隠されたトラップがあります)を見てください。do_settings_sections('permalink');しかし、フォームactionが間違っているため機能しません。

それでは、カスタムページに戻ります。WordPressよりも優れています。

設定、セクション、フィールドを登録する

admin_init 必要なときにフックして、登録関数を呼び出します。

if ( ! empty ( $GLOBALS['pagenow'] )
    and ( 'options-general.php' === $GLOBALS['pagenow']
        or 'options.php' === $GLOBALS['pagenow']
    )
)
{
    add_action( 'admin_init', 't5_sae_register_settings' );
}

ここで重要なのは$GLOBALS['pagenow']options-general.php(出力用)またはoptions.php(検証用)のいずれかでなければなりません。各リクエストで次のコードをすべて呼び出さないでください。ほとんどのチュートリアルとほとんどすべてのプラグインがこれを間違っています。

さて、狂ったように登録しましょう:

  1. ページのオプション値を取得し、いくつかのデフォルトに対して解析します。かなり基本的です。

  2. 名前で設定グループを登録しますplugin:t5_sae_option_group。私は接頭辞付きの名前が好きです、彼らは分類しやすく、この方法を理解しやすいです。

  3. 次に、1と2の2つのセクションを登録します。

  4. そして、最初のセクションに2つ、2つ目のセクションに1つ、合計3つのセクションを追加します。オプション名とエスケープされた値を各フィールドのコールバック関数に渡します。出力ハンドラはデータを変更せず、HTMLを追加するだけです。

function t5_sae_register_settings()
{
    $option_name   = 'plugin:t5_sae_option_name';

    // Fetch existing options.
    $option_values = get_option( $option_name );

    $default_values = array (
        'number' => 500,
        'color'  => 'blue',
        'long'   => ''
    );

    // Parse option values into predefined keys, throw the rest away.
    $data = shortcode_atts( $default_values, $option_values );

    register_setting(
        'plugin:t5_sae_option_group', // group, used for settings_fields()
        $option_name,  // option name, used as key in database
        't5_sae_validate_option'      // validation callback
    );

    /* No argument has any relation to the prvious register_setting(). */
    add_settings_section(
        'section_1', // ID
        'Some text fields', // Title
        't5_sae_render_section_1', // print output
        't5_sae_slug' // menu slug, see t5_sae_add_options_page()
    );

    add_settings_field(
        'section_1_field_1',
        'A Number',
        't5_sae_render_section_1_field_1',
        't5_sae_slug',  // menu slug, see t5_sae_add_options_page()
        'section_1',
        array (
            'label_for'   => 'label1', // makes the field name clickable,
            'name'        => 'number', // value for 'name' attribute
            'value'       => esc_attr( $data['number'] ),
            'option_name' => $option_name
        )
    );
    add_settings_field(
        'section_1_field_2',
        'Select',
        't5_sae_render_section_1_field_2',
        't5_sae_slug',  // menu slug, see t5_sae_add_options_page()
        'section_1',
        array (
            'label_for'   => 'label2', // makes the field name clickable,
            'name'        => 'color', // value for 'name' attribute
            'value'       => esc_attr( $data['color'] ),
            'options'     => array (
                'blue'  => 'Blue',
                'red'   => 'Red',
                'black' => 'Black'
            ),
            'option_name' => $option_name
        )
    );

    add_settings_section(
        'section_2', // ID
        'Textarea', // Title
        't5_sae_render_section_2', // print output
        't5_sae_slug' // menu slug, see t5_sae_add_options_page()
    );

    add_settings_field(
        'section_2_field_1',
        'Notes',
        't5_sae_render_section_2_field_1',
        't5_sae_slug',  // menu slug, see t5_sae_add_options_page()
        'section_2',
        array (
            'label_for'   => 'label3', // makes the field name clickable,
            'name'        => 'long', // value for 'name' attribute
            'value'       => esc_textarea( $data['long'] ),
            'option_name' => $option_name
        )
    );
}

セクションおよびフィールドのコールバックハンドラーはすべてdo_settings_sections( 't5_sae_slug' );、ページを呼び出すと自動的に呼び出されます。すでにそれを行ったので、…

フィールドを印刷する

name属性の作成方法に注意してください。渡さoption_nameれるのは最初の部分で、配列キーは角括弧で囲まれています[]

function t5_sae_render_section_1()
{
    print '<p>Pick a number between 1 and 1000, and choose a color.</p>';
}
function t5_sae_render_section_1_field_1( $args )
{
    /* Creates this markup:
    /* <input name="plugin:t5_sae_option_name[number]"
     */
    printf(
        '<input name="%1$s[%2$s]" id="%3$s" value="%4$s" class="regular-text">',
        $args['option_name'],
        $args['name'],
        $args['label_for'],
        $args['value']
    );
    // t5_sae_debug_var( func_get_args(), __FUNCTION__ );
}
function t5_sae_render_section_1_field_2( $args )
{
    printf(
        '<select name="%1$s[%2$s]" id="%3$s">',
        $args['option_name'],
        $args['name'],
        $args['label_for']
    );

    foreach ( $args['options'] as $val => $title )
        printf(
            '<option value="%1$s" %2$s>%3$s</option>',
            $val,
            selected( $val, $args['value'], FALSE ),
            $title
        );

    print '</select>';

    // t5_sae_debug_var( func_get_args(), __FUNCTION__ );
}
function t5_sae_render_section_2()
{
    print '<p>Makes some notes.</p>';
}

function t5_sae_render_section_2_field_1( $args )
{
    printf(
        '<textarea name="%1$s[%2$s]" id="%3$s" rows="10" cols="30" class="code">%4$s</textarea>',
        $args['option_name'],
        $args['name'],
        $args['label_for'],
        $args['value']
    );
}

ああ、私は関数を導入しましたt5_sae_debug_var()。ここにあります:

function t5_sae_debug_var( $var, $before = '' )
{
    $export = esc_html( var_export( $var, TRUE ) );
    print "<pre>$before = $export</pre>";
}

期待した結果が得られたかどうかを確認するのに役立ちます。

さて、これは非常にうまく機能します。必要なものは1つだけです。

オプション配列を検証する

ブラケット表記を使用したため、値は配列です。各要素を調べて検証するだけです。

function t5_sae_validate_option( $values )
{
    $default_values = array (
        'number' => 500,
        'color'  => 'blue',
        'long'   => ''
    );

    if ( ! is_array( $values ) ) // some bogus data
        return $default_values;

    $out = array ();

    foreach ( $default_values as $key => $value )
    {
        if ( empty ( $values[ $key ] ) )
        {
            $out[ $key ] = $value;
        }
        else
        {
            if ( 'number' === $key )
            {
                if ( 0 > $values[ $key ] )
                    add_settings_error(
                        'plugin:t5_sae_option_group',
                        'number-too-low',
                        'Number must be between 1 and 1000.'
                    );
                elseif ( 1000 < $values[ $key ] )
                    add_settings_error(
                        'plugin:t5_sae_option_group',
                        'number-too-high',
                        'Number must be between 1 and 1000.'
                    );
                else
                    $out[ $key ] = $values[ $key ];
            }
            elseif ( 'long' === $key )
            {
                $out[ $key ] = trim( $values[ $key ] );
            }
            else
            {
                $out[ $key ] = $values[ $key ];
            }
        }
    }

    return $out;
}

これはかなりいです。実稼働環境ではこのようなコードを使用しません。ただし、必要な処理を実行します。検証された値の配列を返します。WordPressは配列をシリアル化し、データベース内のオプション名の下に配列を保存し、を呼び出すと非シリアル化して返しますget_option()


これらはすべて機能しますが、不必要に複雑であり、1998年からマークアップ(<tr valign="top">)を取得し、多くの冗長性を取得しています。

必要なときに設定APIを使用します。代わりにadmin_url( 'admin-post.php' )フォームアクションとして使用し(ソースを参照)、独自の、おそらくよりエレガントなコードで完全な設定ページを作成します。

実際には、ネットワークプラグインを作成するときに設定を行う必要があります。設定APIがそこで機能しないからです。

また、ここで言及しなかったエッジケースや不完全な部分もあります。必要なときに見つけることができます。:)


わあ、ありがとう。これは非常に役立ちます。私が読んだ他の投稿では、ネットワークプラグインについては何も言及していませんでした。これは、将来のために心に留めておくべき重要なメモです。
ビヨン

これの補遺です。チェックボックスを表示/保存しようとしている場合、コールバックコードを次のように変更しました: '<input type = "checkbox" id = "%3 $ s" name = "%1 $ s [%2 $ s] value =" %4 $ s "'
。checked

答えを確認すると、単一のコロンを含むplugin:t5_sae_option_groupの使用に困惑しています。徹底的に調べましたが、この構文の説明は見つかりませんでした。PHPドキュメントでこれについて説明してください。おかげで

@ user50909:これらは、私には単純な文字列識別子のように見えます。PHPの構文が要因になることはありません。
s_ha_dum 14

1
試してみてください@Dan basename( $_SERVER['REQUEST_URI'] )
FUXIA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.