API de paramètres avec exemple de tableaux

32

J'utilise le livre de développement du plugin Wrox WordPress comme référence principale pour commencer à utiliser un nouveau plugin et je comprends que tous les paramètres peuvent être sauvegardés sous 1 tableau, mais le livre ne donne pas d'exemple et tout ce que je suis Trouver sur le web semble si différent d'un exemple à l'autre. La seconde moitié d'un article de Konstantin me rapproche mais j'aimerais vraiment voir un exemple plus complet avec plusieurs champs.

Bjorn
la source

Réponses:

32

Réponse courte: vos namevaleurs d'attribut doivent utiliser le schéma option_name[array_key]. Alors, quand vous utilisez…

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

… Vous obtenez un tableau comme valeur d'option dans votre fonction de validation:

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

PHP le fait pour vous, ce n'est pas une fonctionnalité de WordPress. :)

Comment faire fonctionner cela avec les paramètres de l'API?

Disons que nous voulons cette page d’options et que toutes les valeurs doivent être stockées dans une option et validées dans une fonction.

entrez la description de l'image ici

La page des options

Nous avons besoin du hook admin_menuet de deux fonctions: une pour enregistrer la page, une pour afficher le résultat.

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
}

Le formulaire actiondoit être options.php, sinon la validation ne sera pas appelée. Regardez la source PHP de wp-admin/options-permalink.php- il y a un piège caché do_settings_sections('permalink');- mais cela ne peut pas fonctionner car la formeaction est faux.

Revenons maintenant à notre page personnalisée. Nous le faisons mieux que WordPress.

Enregistrer les paramètres, les sections et les champs

Nous accrochons admin_init quand nous en avons besoin et appelons une fonction d'enregistrement.

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

La partie importante ici est: $GLOBALS['pagenow']doit être soit options-general.php(pour la sortie) ouoptions.php (pour la validation). N'appelez pas tout le code suivant sur chaque demande. La plupart des tutoriels et presque tous les plugins se trompent.

Ok, inscrivons-nous comme un fou:

  1. Nous récupérons les valeurs d'option pour notre page et les analysons en fonction de certaines valeurs par défaut. Assez basique.

  2. Nous enregistrons un groupe de paramètres avec le nom plugin:t5_sae_option_group. J'aime les noms préfixés, ils sont plus faciles à trier et à comprendre de cette façon.

  3. Ensuite, nous enregistrons deux sections, 1 et 2.

  4. Et nous ajoutons trois sections, deux pour la première et une pour la seconde. Nous passons le nom de l'option et la valeur échappée aux fonctions de rappel pour chaque champ. Les gestionnaires de sortie ne doivent pas modifier les données, mais juste ajouter du 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
        )
    );
}

Tous les gestionnaires de rappel pour les sections et les champs seront appelés automatiquement lorsque nous appellerons do_settings_sections( 't5_sae_slug' );dans notre page. Nous l'avons déjà fait, il nous faut juste…

Imprimer les champs

Notez comment les nameattributs sont construits: la option_namepremière partie est passée , la clé de tableau suit entre crochets [].

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, j'ai introduit une fonction t5_sae_debug_var(). C'est ici:

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

Utile pour voir si nous avons obtenu ce que nous attendions.

Maintenant, ça marche plutôt bien, il suffit d’une chose:

Valider le tableau d'options

Comme nous avons utilisé la notation entre crochets, notre valeur est un tableau. Il suffit de parcourir chaque élément et de le valider.

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

C'est plutôt moche; Je n'utiliserais pas un tel code en production. Mais il fait ce qu’il devrait: il retourne un tableau de valeurs validé. WordPress va sérialiser le tableau, le stocker sous notre nom d'option dans la base de données et le renvoyer non sérialisé, lorsque nous appelons get_option().


Tout cela fonctionne, mais ce n'est pas compliqué, nous obtenons un balisage à partir de 1998 ( <tr valign="top">), ainsi que de nombreux redondances.

Utilisez les paramètres de l'API lorsque vous devez. admin_url( 'admin-post.php' )Vous pouvez également utiliser une action de formulaire (regardez son source) et créer la page de paramètres complète avec votre propre code, probablement plus élégant.

En fait, vous devez le faire lorsque vous écrivez un plug-in de réseau, car l'API de paramètres ne fonctionne pas là-bas.

Il y a aussi des cas particuliers et des parties incomplètes que je n'ai pas mentionnées ici - vous les trouverez quand vous en aurez besoin. :)

fuxia
la source
Ouah merci. C'est très utile. Aucun des autres articles que j'ai lus n'a mentionné quoi que ce soit à propos des plugins réseau, ce qui est une note importante que je garderai à l'esprit pour l'avenir.
Bjorn
Juste un addendum à cela. Si vous essayez d’afficher / stocker des cases à cocher, j’ai modifié le code de rappel comme suit: '<type d’entrée = "case à cocher" id = "% 3 $ s" name = "% 1 $ s [% 2 $ s] value =" % 4 $ s "'. Vérifié (' on ', $ args [' valeur '], false).' /> '
joesk
Passant en revue la réponse, l'utilisation du plug-in: t5_sae_option_group, qui inclut un seul deux-points, me laisse perplexe . J'ai regardé de manière exhaustive et je n'ai pas trouvé d'explication de cette syntaxe. Pourriez-vous indiquer une explication à ce sujet dans la documentation PHP, s'il vous plaît? Merci
@ user50909: ceux-ci ressemblent à de simples identificateurs de chaîne. La syntaxe PHP ne devrait pas être un facteur.
s_ha_dum
1
@Dan Essayez basename( $_SERVER['REQUEST_URI'] ).
fuxia