Pengaturan API dengan contoh array

32

Saya menggunakan buku pengembangan plugin Wrox WordPress sebagai referensi utama untuk memulai dengan plugin baru dan saya mengerti semua pengaturan dapat disimpan sebagai 1 array tetapi buku tidak memberikan contoh ini dan semua hal yang saya menemukan di web tampaknya sangat berbeda dari satu contoh ke yang lain. Paruh kedua posting oleh Konstantin membuat saya dekat tapi saya benar-benar ingin melihat contoh yang lebih lengkap dengan beberapa bidang.

Bjorn
sumber

Jawaban:

32

Jawaban singkat: namenilai atribut Anda harus menggunakan skema option_name[array_key]. Jadi, ketika Anda menggunakan ...

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

... Anda mendapatkan array sebagai nilai opsi dalam fungsi validasi Anda:

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

PHP melakukan itu untuk Anda, ini bukan fitur WordPress. :)

Bagaimana cara membuatnya bekerja dengan pengaturan API?

Katakanlah, kami menginginkan halaman opsi ini, dan semua nilai harus disimpan dalam satu opsi dan divalidasi dalam satu fungsi.

masukkan deskripsi gambar di sini

Halaman opsi

Kami membutuhkan hook admin_menudan dua fungsi: satu untuk mendaftarkan halaman, satu untuk membuat output.

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
}

Formulir actionharus options.php, atau validasi tidak akan dipanggil. Lihatlah sumber PHP wp-admin/options-permalink.php- ada jebakan tersembunyi do_settings_sections('permalink');- tetapi tidak dapat bekerja karena formulirnya actionsalah.

Sekarang, kembali ke halaman khusus kami. Kami membuatnya lebih baik dari WordPress.

Mendaftar pengaturan, bagian dan bidang

Kami menghubungkan ke admin_init saat kami membutuhkannya dan memanggil fungsi pendaftaran.

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

Bagian penting di sini adalah: $GLOBALS['pagenow']harus berupa options-general.php(untuk output) atau options.php(untuk validasi). Jangan panggil semua kode berikut pada setiap permintaan. Sebagian besar tutorial dan hampir semua plugin salah.

Oke, mari daftar seperti orang gila:

  1. Kami mengambil nilai opsi untuk halaman kami dan menguraikannya terhadap beberapa default. Cukup mendasar.

  2. Kami mendaftarkan grup pengaturan dengan nama plugin:t5_sae_option_group. Saya suka nama yang diawali, mereka lebih mudah disortir dan dipahami dengan cara ini.

  3. Kemudian kami mendaftarkan dua bagian, 1 dan 2.

  4. Dan kami menambahkan tiga bagian, dua untuk bagian pertama, satu untuk yang kedua. Kami meneruskan nama opsi dan nilai lolos ke fungsi panggilan balik untuk setiap bidang. Penangan keluaran tidak boleh mengubah data, cukup tambahkan beberapa 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
        )
    );
}

Semua penangan panggilan balik untuk bagian dan bidang akan dipanggil secara otomatis ketika kami memanggil do_settings_sections( 't5_sae_slug' );halaman kami. Kami sudah melakukannya, jadi kami hanya perlu ...

Cetak bidangnya

Perhatikan bagaimana nameatribut dibangun: yang dilewati option_nameadalah bagian pertama, kunci array mengikuti tanda kurung siku [].

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']
    );
}

Oh, saya memperkenalkan fungsi t5_sae_debug_var(). Ini dia:

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

Berguna untuk melihat apakah kita mendapatkan apa yang kita harapkan.

Sekarang, ini bekerja dengan sangat baik, kita hanya perlu satu hal:

Validasikan array opsi

Karena kami menggunakan notasi braket, nilai kami adalah array. Kami hanya harus berjalan melalui setiap elemen dan memvalidasinya.

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;
}

Ini agak jelek; Saya tidak akan menggunakan kode seperti itu dalam produksi. Tapi ia melakukan apa yang seharusnya: mengembalikan array nilai yang divalidasi. WordPress akan membuat serial array, menyimpannya di bawah nama opsi kami di database dan mengembalikannya tidak teridentifikasi, ketika kita menelepon get_option().


Semua ini berfungsi, tetapi tidak perlu rumit, kami mendapatkan markup dari 1998 ( <tr valign="top">), dan banyak redudansi.

Gunakan API pengaturan saat Anda harus. Sebagai alternatif gunakan admin_url( 'admin-post.php' )sebagai tindakan formulir (lihat sumbernya) dan buat halaman pengaturan lengkap dengan kode Anda sendiri, mungkin kode yang lebih elegan.

Sebenarnya, Anda harus melakukannya ketika Anda menulis sebuah plugin jaringan, karena pengaturan API tidak berfungsi di sana.

Ada juga beberapa case tepi dan bagian tidak lengkap yang tidak saya sebutkan di sini - Anda akan menemukannya ketika Anda membutuhkannya. :)

fuxia
sumber
Wow terima kasih. Ini sangat membantu. Tidak ada tulisan lain yang saya baca yang menyebutkan tentang plugin jaringan, yang merupakan catatan penting yang akan saya ingat untuk masa depan.
Bjorn
Hanya tambahan untuk ini. Jika Anda mencoba menampilkan / menyimpan kotak centang, saya telah mengubah kode panggilan balik menjadi: '<input type = "checkbox" id = "% 3 $ s" name = "% 1 $ s [% 2 $ s] value =" % 4 $ s "'. Checked (' on ', $ args [' value '], false).' /> '
joesk
Meninjau jawaban saya bingung dengan penggunaan plugin: t5_sae_option_group yang mencakup satu titik dua. Saya telah melihat secara mendalam dan tidak menemukan penjelasan tentang sintaks ini. Bisakah Anda mengarahkan penjelasannya ke dokumentasi PHP? Terima kasih
@ user50909: yang terlihat seperti pengenal string sederhana bagi saya Sintaks PHP seharusnya tidak menjadi faktor.
s_ha_dum
1
@Bisa Mencoba basename( $_SERVER['REQUEST_URI'] ).
fuxia