API delle impostazioni con esempio di array


32

Sto usando il libro di sviluppo del plugin Wrox WordPress come riferimento principale per iniziare con un nuovo plugin e capisco che tutte le impostazioni possono essere salvate come 1 array ma il libro non fornisce un esempio di questo e di tutte le cose che sto la ricerca sul Web sembra così diversa da un esempio all'altro. La seconda parte di un post di Konstantin mi avvicina ma mi piacerebbe davvero vedere un esempio più completo con più campi.

Risposte:


32

Risposta breve: i namevalori degli attributi devono utilizzare lo schema option_name[array_key]. Quindi, quando usi ...

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

... ottieni un array come valore di opzione nella tua funzione di validazione:

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

PHP lo fa per te, questa non è una funzionalità di WordPress. :)

Come farlo funzionare con l'API delle impostazioni?

Diciamo, vogliamo questa pagina di opzioni e tutti i valori dovrebbero essere archiviati in un'opzione e convalidati in una funzione.

inserisci qui la descrizione dell'immagine

La pagina delle opzioni

Abbiamo bisogno dell'hook admin_menue di due funzioni: una per registrare la pagina, una per rendere l'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
}

Il modulo actiondeve essere options.phpo la convalida non verrà chiamata. Guarda la fonte PHP di wp-admin/options-permalink.php- c'è una trappola nascosta do_settings_sections('permalink');- ma non può funzionare perché il modulo actionè sbagliato.

Ora, torniamo alla nostra pagina personalizzata. Lo rendiamo migliore di WordPress.

Registra impostazioni, sezioni e campi

Ci agganciamo admin_init quando ne abbiamo bisogno e chiamiamo una funzione di registrazione.

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

La parte importante qui è: $GLOBALS['pagenow']deve essere options-general.php(per l'output) o options.php(per la convalida). Non chiamare tutto il seguente codice su ogni richiesta. La maggior parte dei tutorial e quasi tutti i plugin ottengono questo errore.

Ok, registriamoci come un matto:

  1. Recuperiamo i valori delle opzioni per la nostra pagina e li analizziamo in base ad alcuni valori predefiniti. Piuttosto semplice.

  2. Registriamo un gruppo di impostazioni con il nome plugin:t5_sae_option_group. Mi piacciono i nomi prefissati, sono più facili da ordinare e da comprendere in questo modo.

  3. Quindi registriamo due sezioni, 1 e 2.

  4. E aggiungiamo tre sezioni, due per la prima sezione, una per la seconda. Passiamo il nome dell'opzione e il valore di escape alle funzioni di callback per ciascun campo. I gestori di output non devono modificare i dati, basta aggiungere un po 'di 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
        )
    );
}

Tutti quei gestori di callback per le sezioni e i campi verranno chiamati automaticamente quando chiamiamo do_settings_sections( 't5_sae_slug' );nella nostra pagina. Lo abbiamo già fatto, quindi dobbiamo solo ...

Stampa i campi

Nota come namesono costruiti gli attributi: il passato option_nameè la prima parte, la chiave dell'array segue tra parentesi quadre [].

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, ho introdotto una funzione t5_sae_debug_var(). Ecco qui:

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

Utile per vedere se abbiamo ottenuto ciò che ci aspettavamo.

Ora funziona abbastanza bene, abbiamo bisogno solo di una cosa:

Convalida l'array di opzioni

Poiché abbiamo usato la notazione parentesi, il nostro valore è un array. Non ci resta che esaminare ogni elemento e convalidarlo.

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

Questo è piuttosto brutto; Non userei questo codice in produzione. Ma fa quello che dovrebbe: restituisce un array validato di valori. WordPress serializzerà l'array, lo memorizzerà con il nostro nome opzione nel database e lo restituirà non serializzato, quando lo chiamiamo get_option().


Tutto funziona, ma è inutilmente complicato, otteniamo il markup dal 1998 ( <tr valign="top">) e molti licenziamenti.

Utilizzare l'API delle impostazioni quando è necessario. In alternativa, usa admin_url( 'admin-post.php' )come azione del modulo (guarda la sua fonte) e crea la pagina delle impostazioni complete con il tuo codice, probabilmente più elegante.

In realtà, devi farlo quando scrivi un plug-in di rete, perché l'API delle impostazioni non funziona lì.

Ci sono anche alcuni casi limite e parti incomplete che non ho menzionato qui - li troverai quando ne hai bisogno. :)


Wow grazie. Questo è molto utile Nessuno degli altri post che ho letto menzionava nulla sui plugin di rete, che è una nota importante che terrò a mente per il futuro.
Bjorn,

Solo un addendum a questo. Se stai cercando di visualizzare / archiviare caselle di controllo, ho modificato il codice di richiamata in modo che sia: '<input type = "checkbox" id = "% 3 $ s" name = "% 1 $ s [% 2 $ s] value =" % 4 $ s "'. Checked (' on ', $ args [' value '], false).' /> '
joesk

Rivedere la risposta Sono perplesso dall'uso del plugin: t5_sae_option_group che include due punti. Ho guardato esaurientemente e non ho trovato una spiegazione di questa sintassi. Potresti indicare una spiegazione di questo nella documentazione di PHP per favore? Grazie

@ user50909: quelli mi sembrano semplici identificatori di stringhe. La sintassi di PHP non dovrebbe essere un fattore.
s_ha_dum,

1
@Dan Try basename( $_SERVER['REQUEST_URI'] ).
fuxia
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.