it-swarm.com.de

Einstellungs-API mit Beispiel für Arrays

Ich verwende das Wrox WordPress-Plugin-Entwicklungsbuch als primäre Referenz für den Einstieg in ein neues Plugin und ich verstehe, dass alle Einstellungen als 1 Array gespeichert werden können, aber das Buch gibt kein Beispiel dafür und all das, was ich habe Das Finden im Web scheint von Beispiel zu Beispiel so unterschiedlich zu sein. Die zweite Hälfte eines Posts von Konstantin bringt mich näher, aber ich würde wirklich gerne ein vollständigeres Beispiel mit mehreren Feldern sehen.

32
Bjorn

Kurze Antwort: Ihre name Attributwerte müssen das Schema option_name[array_key] verwenden. Also, wenn Sie verwenden ...

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

… Erhalten Sie in Ihrer Validierungsfunktion ein Array als Optionswert:

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

PHP erledigt das für Sie, dies ist keine WordPress-Funktion. :)

Wie funktioniert das mit der Einstellungs-API?

Angenommen, wir möchten diese Optionsseite, und alle Werte sollten in einer Option gespeichert und in einer Funktion validiert werden.

enter image description here

Die Optionsseite

Wir brauchen den Hook admin_menu und zwei Funktionen: eine zum Registrieren der Seite, eine zum Rendern der Ausgabe.

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
}

Das Formular action muss options.php sein, sonst wird die Validierung nicht aufgerufen. Schauen Sie sich die PHP Quelle von wp-admin/options-permalink.php an - es gibt eine versteckte Falle do_settings_sections('permalink'); - aber es kann nicht funktionieren, weil die Form action falsch ist.

Nun zurück zu unserer benutzerdefinierten Seite. Wir machen es besser als WordPress.

Registrieren Sie Einstellungen, Abschnitte und Felder

Wir hängen uns an admin_init wenn wir es brauchen und rufen eine Registrierungsfunktion auf.

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

Der wichtige Teil hier ist: $GLOBALS['pagenow'] muss entweder options-general.php (für die Ausgabe) oder options.php (für die Validierung) sein. Rufen Sie nicht bei jeder Anforderung den gesamten folgenden Code auf. Die meisten Tutorials und fast alle Plugins verstehen das falsch.

Okay, lass uns wie verrückt registrieren:

  1. Wir rufen die Optionswerte für unsere Seite ab und analysieren sie anhand einiger Standardwerte. Ziemlich einfach.

  2. Wir registrieren eine Einstellungsgruppe mit dem Namen plugin:t5_sae_option_group. Ich mag Präfixnamen, sie sind einfacher zu sortieren und auf diese Weise zu verstehen.

  3. Dann registrieren wir zwei Abschnitte, 1 und 2.

  4. Und wir fügen drei Abschnitte hinzu, zwei für den ersten Abschnitt und einen für den zweiten. Wir übergeben den Optionsnamen und den Wert escaped an die Rückruffunktionen für jedes Feld. Ausgabehandler sollten keine Daten ändern, sondern nur HTML hinzufügen.

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

Alle diese Callback-Handler für die Abschnitte und Felder werden automatisch aufgerufen, wenn wir auf unserer Seite do_settings_sections( 't5_sae_slug' ); aufrufen. Das haben wir schon gemacht, also müssen wir nur ...

Drucken Sie die Felder aus

Beachten Sie, wie die Attribute name erstellt werden: Der übergebene option_name ist der erste Teil, der Array-Schlüssel folgt in eckigen Klammern [].

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, ich habe eine Funktion t5_sae_debug_var() eingeführt. Hier ist es:

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

Nützlich, um zu sehen, ob wir das bekommen haben, was wir erwartet hatten.

Das funktioniert ganz gut, wir brauchen nur eins:

Überprüfen Sie das Optionsarray

Da wir die Klammernotation verwendet haben, ist unser Wert ein Array. Wir müssen nur durch jedes Element gehen und es validieren.

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

Das ist ziemlich hässlich; Ich würde keinen solchen Code in der Produktion verwenden. Aber es tut, was es sollte: Es gibt ein validiertes Array von Werten zurück. WordPress serialisiert das Array, speichert es unter unserem Optionsnamen in der Datenbank und gibt es unserialisiert zurück, wenn wir get_option() aufrufen.


All dies funktioniert, aber es ist unnötig kompliziert, wir bekommen Markup von 1998 (<tr valign="top">) und viele Redundanzen.

Verwenden Sie die Einstellungs-API, wenn Sie müssen. Verwenden Sie alternativ admin_url( 'admin-post.php' ) als Formularaktion (sehen Sie sich deren Quelle an) und erstellen Sie die vollständige Einstellungsseite mit Ihrem eigenen, wahrscheinlich eleganteren Code.

Eigentlich müssen Sie dies tun, wenn Sie ein Netzwerk-Plugin schreiben, da die Einstellungs-API dort nicht funktioniert.

Es gibt auch einige Edge-Fälle und unvollständige Teile, die ich hier nicht erwähnt habe. Sie werden sie finden, wenn Sie sie benötigen. :)

32
fuxia