web-dev-qa-db-fra.com

API de paramètres avec exemple de tableaux

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 enregistrés dans un 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 partie d'un message de Konstantin me rapproche mais j'aimerais vraiment voir un exemple plus complet avec plusieurs champs.

32
Bjorn

Réponse courte: vos valeurs d'attribut name 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.

enter image description here

La page des options

Nous avons besoin du hook admin_menu et 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 action doit être options.php, sinon la validation ne sera pas appelée. Examinez 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 le formulaire action est incorrect.

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

Enregistrer les paramètres, les sections et les champs

Nous nous connectons à admin_init lorsque 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), soit options.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 escaped 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 ces gestionnaires de rappel pour les sections et les champs seront appelés automatiquement lorsque nous appelons 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 attributs name sont construits: le option_name transmis est la première partie, la clé du 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 ce 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 sans numéro de série, lorsque nous appelons get_option().


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

Utilisez les paramètres de l'API lorsque vous devez. Vous pouvez également utiliser admin_url( 'admin-post.php' ) comme 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 des paramètres ne fonctionne pas là-bas.

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

32
fuxia