Quali sono i vantaggi dell'API delle impostazioni?


13

Permettetemi di prefigurarlo dicendo che non lavoro quasi mai con WordPress - in effetti, l'ultima volta che ho fatto un sito in WordPress è tornato durante la 2.2. Ieri ho fatto un bel casino di tutto e ho fatto diverse domande qui cercando di far funzionare un plugin di menu di base.

Ora ho il plugin perfettamente funzionante e si comportano esattamente come mi aspetto, quindi ho deciso di apportare piccole modifiche qua e là per aggiungere funzionalità e compatibilità, incluso l'uso dell'API delle impostazioni. Tuttavia, un momento molto breve nella lettura di tutorial su questa API e sono diventato piuttosto confuso, quindi questa confusione si è solo approfondita mentre continuavo a leggere e ho cercato di implementare gli esempi, il che è stato reso ancora più difficile dal fatto che il mio plugin è implementato come classe .

A meno che non stia facendo qualcosa di sbagliato, da quello che ho capito per usare l'API Impostazioni richiede la creazione di una nuova funzione PER IMPOSTAZIONE. Ciò significa 3-5 funzioni per il plugin medio e fino a centinaia per plugin più avanzati. Sembra ridicolo scrivere queste molte funzioni (e sviluppare un sistema di denominazione per evitare di confonderle) quando è possibile importare altrettanto facilmente tutte le $_POSTvariabili applicabili in un array e rinunciare all'intero pasticcio.

Forse sono vecchio stile, ma a meno che non ci sia qualcosa da guadagnare da esso non vedo il motivo per triplicare o quadruplicare quanto codice sto scrivendo. Ecco come ho gestito le opzioni prima di provare ad aggiungere l'API delle impostazioni:

    function __construct() {
        /* constructor stuff */
        $this->options = $this->db_options = get_option( 'de-menu-options' );
        if( $this->options === false ){
            $this->options = $this->defaults;
        }
        if (is_admin()) {
            add_action('admin_menu', array(&$this, 'admin_menu'));
        }   
        /* more stuff */

        // When WordPress shuts down we store changes to options
        add_action('shutdown', array(&$this, 'update'));
    }

    public function admin_menu() {
        add_options_page('DE Menu Options', 'DE Menu', 'manage_options', 'de-menu-options', array(&$this, 'options'));
        add_option('de-menu-options', $this->options);
    }

    public function options() {
        if (!current_user_can('manage_options')) {
            wp_die( __('You do not have sufficient permissions to access this page.') );
        }
        if ( !empty($_POST) && check_admin_referer('de-menu-options') ) {
            // These options are saved to the database at shutdown
            $this->options = array(
                "columns" => $_POST["de-menu-columns"],
                "maintenance" => $_POST["de-menu-maintenance"]
            );
            echo 'DE Menu options saved';
        }
?>

<div class="wrap">
    <h2>DE Menu Plugin</h2>
    <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
        <?php settings_fields('de-menu-options'); ?>
        <input type="checkbox" name="de-menu-maintenance" />
        <label for="de-menu-columns">Columns:</label>
        <input type="text" name="de-menu-columns" value="<?php echo $this->options['columns']; ?>" />
        <p class="submit">
        <input type="submit" name="de-menu-submit" value="Update Options »" />
        </p>
    </form>
</div>
<?php
    }

    function update() {
        // By storing all changes at the end we avoid multiple database calls
        $diff = array_diff( $this->options, $this->db_options );
        if( !empty( $diff )  ){
            update_option('de-menu-options', $this->options);
        }
    }

Ora con l'API delle impostazioni ho qualcosa di più simile al seguente:

    function __construct() {
        /* constructor stuff */
        // Do I load options? Will they be loaded for me? Who knows?
        if (is_admin()) {
            add_action('admin_menu', array(&$this, 'admin_menu'));
            add_action('admin_init', array(&$this, 'admin_init'));
        }   
        /* more stuff */
        // Settings API should update options for me... I think
    }

    public function admin_menu() {
        add_options_page('DE Menu Options', 'DE Menu', 'manage_options', 'de-menu-options', array(&$this, 'options'));
        add_option('de-menu-options', $this->options);
    }

    public function admin_init() {
        register_setting('de-menu-options','de-menu-options',array(&$this,'validate'));
        add_settings_section('de-menu-main-options', 'Main Settings', 'options_section', 'de-menu-options');
        add_settings_field('de-menu-maintenance', 'Maintenance Mode', array(&$this,'options_maintenance'), 'de-menu-options', 'de-menu-main-options');
        add_settings_field('de-menu-columns', 'Columns', array(&$this,'options_columns'), 'de-menu-options', 'de-menu-main-options');
    }

    public function options() {
        if (!current_user_can('manage_options')) {
            wp_die( __('You do not have sufficient permissions to access this page.') );
        }
        if ( !empty($_POST) && check_admin_referer('de-menu-options') ) {
            // These options are saved to the database at shutdown
            $this->options = array(
                "columns" => $_POST["de-menu-columns"],
                "maintenance" => $_POST["de-menu-maintenance"]
            );
            echo 'DE Menu options saved';
        }
?>

<div class="wrap">
    <h2>DE Menu Plugin</h2>
    <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
        <?php settings_fields('de-menu-options'); ?>
        <?php do_settings_sections('de-menu-options'); ?>
        <p class="submit">
        <input type="submit" name="de-menu-submit" value="Update Options »" />
        </p>
    </form>
</div>
<?php
    }

    public function options_section() {
        echo '<p>' . __('Main description of this section here.','de-menu-lang') . '</p>';
    }

    public function options_maintenance() {
        echo "<input id='de-menu-maintenance' name='options[maintenance]' type='checkbox' />";
    }

    public function options_columns() {
        echo "<input id='de-menu-columns' name='options[columns]' type='checkbox' value=".$this->options['columns']."/>";
    }

    function validate($options) {
        return $options; // I guess?
    }

È probabilmente dolorosamente ovvio dalle barre di scorrimento che il codice è già più lungo con solo due opzioni. È altrettanto ovvio dai commenti che non capisco del tutto quello che sto facendo. Quindi c'è la questione di avere 5 nuove funzioni (e rimuovere solo 1) per realizzare tutto ciò.

Quindi, quale vantaggio sto ottenendo da tutto questo lavoro extra?


Non utilizzarli per tali casi. Penso che siano pensati per i principianti di PHP, che hanno bisogno di 3-4 opzioni all'interno del loro plugin / tema. Questa è una delle "caratteristiche" che non avrebbero mai dovuto essere implementate ... È fondamentalmente un'API per un'altra API :)
onetrickpony,

3
Uso l'API delle impostazioni per tutto ciò che scrivo, tutto dipende da come la usi, nota che puoi usare l'API senza nemmeno usare add_settings_sectione add_settings_field, quelle due funzioni aggiungono più spazio al tuo codice, evitali e eviti il ​​gonfiamento.
t31os,

1
Faccio la stessa cosa di t3los: registro l'impostazione stessa, quindi scrivo semplicemente i moduli in HTML nella mia pagina delle impostazioni. Se vuoi vedere un modo davvero semplice per farlo e conservare il codice per dopo, dai un'occhiata al plugin SEO per WordPress di Yoast.
chrisguitarguy,

Risposte:


8

Il mio punto di vista è che lo scopo principale e i vantaggi dell'API Impostazioni sono la struttura .

Aiuta a mantenere configurazioni complesse delle impostazioni:

  • ordinato (logica di registrazione e sezioni);
  • sicuro (nonces, callback di validazione);
  • estensibile (aggancio in un'altra pagina o possibilità di essere agganciato).

Come con qualsiasi tale sovraccarico strutturale, avvantaggia casi d'uso più complessi e benefici meno semplici.

In questo modo puoi implementare tutto ciò che fa l'API Impostazioni senza usarla. La domanda è se puoi riuscirci in modo affidabile, sicuro ed estensibile.


Finalmente ho avuto la mia pagina Impostazioni funzionante con l'aiuto di questo tutorial: alisothegeek.com/2011/01/wordpress-settings-api-tutorial-1 e con l'aiuto delle istruzioni switch e delle funzioni di aiuto devo dire che le cose ora sono più ordinate nel mio codice (il che è carino dato che ho intenzione di passare dalle mie due impostazioni di test a 15-20 impostazioni totali).
Stevendesu,

1
@steven_desu sì, lo scherzo è che tutti coloro che usano l'API delle impostazioni scrivono un framework per questo. :) Le funzioni di supporto delle coppie sono quasi inevitabili. Si noti inoltre che l'API delle impostazioni non è considerata finalizzata e ci sono piani (vaghi) per migliorarla in futuro (penso che sia stata menzionata nel contesto di piani 3.3).
Rarst

1
Spero sicuramente che sia migliorato. Onestamente non vedo alcun vantaggio sull'API delle impostazioni, ma piuttosto ogni vantaggio che sto godendo ora è il risultato del framework che ho preso in prestito per questo. Mi piace il fatto che tutti gli elementi del modulo siano ora generati dinamicamente con lo stesso aspetto ... ma questa non è l'API delle impostazioni. Mi piace che le impostazioni predefinite e le impostazioni di registrazione siano gestite dalle stesse definizioni ... ma che non sia API delle impostazioni. Mi piace il fatto che jQuery non solo renda belli i moduli, ma sia progressivamente migliorato - ma ho dovuto codificare manualmente il miglioramento progressivo ...
stevendesu

5

Se si utilizzano correttamente i callback, non è necessario tutto il codice ridondante. Ecco come implementare l'API delle impostazioni, in modo completamente scalabile .

Vantaggi (tra le altre cose):

  • L'API delle impostazioni forza la sanificazione di dati utente non attendibili.
  • L'API delle impostazioni impone che le opzioni vengano registrate come array di opzioni, risultando in una singola voce DB wp_options, anziché voci discrete nel database per ogni opzione
  • L'API delle impostazioni facilita la protezione avanzata del modulo delle impostazioni
  • L'API delle impostazioni facilita l'interfaccia utente dell'amministratore coerente con l'interfaccia utente dell'amministratore principale, con conseguente migliore UX

Quindi forza essenzialmente gli standard estetici e di sicurezza che stavo già seguendo senza il suo aiuto? Leggerò il tutorial che hai collegato, però. Se rende l'API delle impostazioni semplice come codificare manualmente i moduli (o più facilmente) accetterò questa risposta
stevendesu,

Sei consapevole che il codice sorgente che hai indicato implementa le funzioni oenology_get_settings_by_tab()e oenology_get_default_optionssenza prima definirle? Ho pensato che fosse abbastanza male con 209 righe di codice (dopo aver rimosso commenti e righe vuote), ma una volta definite quelle funzioni sarà ancora più lungo ... Per quattro opzioni?
Stevendesu,

Sono definiti altrove. Non oenology_get_settings_by_tab()è veramente rilevante per quello che stai facendo. Ma si hanno per definire la forma-campo markup da qualche parte , proprio come si deve per convalidare l'input dell'utente / disinfettare in qualche modo , quindi se si sta facendo bene, avrai tutto ciò che lo stesso codice pure.
Chip Bennett,

0

Grazie per aver pubblicato questo, mi chiedevo esattamente la stessa cosa. Molte funzioni.

Per ridurli è possibile memorizzare le opzioni come matrici. Wordpress serializza i dati per te. Ciò consente di risparmiare codice (o funzioni comunque), ma peggiora i dati. Ad esempio, se si desidera ordinare, modificare a mano, esportare, ecc., Le tabelle avranno questi valori serializzati. D'altra parte, il tuo plugin aggiunge meno voci alla tabella delle opzioni e sono più facili da ripulire.

Quindi, ecco il tuo codice rifatto. Alcune note:

  • Il mio esempio mostra entrambe le opzioni semplici (de_w, de_h) e un'opzione di array (de_width_height).
  • Disinfetta sempre l'input dell'utente. Nell'esempio ho usato numeri interi perché sono facili da disinfettare.
  • Non è necessario $ _POST, nonces, check_admin_referer (), update_option (), ecc., Quando si utilizza l'API delle impostazioni.
  • Il salvataggio avviene al caricamento della pagina successiva, non all'arresto. Quindi WP reindirizza alla tua pagina. Quindi per eseguire il debug, stampa un po 'di output e chiama wp_die () in una delle funzioni di validazione.
  • L'azione del modulo è sempre "options.php". Ecco come funziona l'API delle impostazioni. Non usare nient'altro. Bene, puoi usare admin_url ('options.php') se vuoi.
  • WP stamperà il messaggio di salvataggio per te.
  • Miglioramenti non inclusi qui: utilizzo <label>per accessibilità. Utilizzando add_settings_error (), settings_error (), che gestisce i messaggi e gli errori. Questo è spesso l'unico motivo per avere funzioni di convalida separate per ciascuna opzione. Di seguito puoi vedere validate_w () e validate_h () potrebbe essere una funzione. Ho cercato di sottrarre i messaggi, ma non ricordo abbastanza informazioni nel callback di convalida, come ricordo. Ad esempio su quale campo stai lavorando.
  • Le funzioni di callback di convalida ottengono un valore $ _POST non elaborato dall'API delle impostazioni. Mi piace nominare il parametro come tale, $ raw. Per l'opzione array, ottieni un array, come la magia.
  • Modifica: $ this è meglio di & $ this.

Codice:

<?php
$foo= new de_Foo();
class de_Foo {
function __construct() {
    if (is_admin()) {
        add_action('admin_menu', array($this, 'admin_menu'));
        add_action('admin_init', array($this, 'admin_init'));
    } 
}
public function admin_menu() {
    add_options_page(
       'DE Menu Options',
       'DE Menu',
       'manage_options',
       'de-menu-options',
       array($this,'xoxptions')
    );
    // add_option('de-menu-options', $this->options);
}
public function admin_init() {
 register_setting(
      'de-menu-settings-group',
      'de_w',
      array($this, 'validate_w')
 );
 register_setting(
      'de-menu-settings-group',
      'de_h',
      array($this, 'validate_h')
 );
 register_setting(
      'de-menu-settings-group',
      'de_width_height',
      array($this, 'validate_width_height')
 );
 add_settings_section(
      'de-menu-settings-section-size',
      'Size',
      array($this, 'settings_section_size_render'),
      'de-menu-options'
 );
 add_settings_field(
      'de_w',
      'W',
      array($this, 'w_render'),
      'de-menu-options',
      'de-menu-settings-section-size'
 );
 add_settings_field(
      'de_h',
      'H',
      array($this, 'h_render'),
      'de-menu-options',
      'de-menu-settings-section-size'
 );
 add_settings_field(
      'de_width_height',
      'Width / Height',
      array($this, 'width_height_render'),
      'de-menu-options',
      'de-menu-settings-section-size'
 );
}
public function options() {
    if (!current_user_can('manage_options')) {
        wp_die( __('You do not have sufficient permissions to access this page.') );
    }
////////////////////////////
// no no no
////////////////////////////
//         if ( !empty($_POST) && check_admin_referer('de-menu-options') ) {
//             // These options are saved to the database at shutdown
//             $this->options = array(
//                 "columns" => $_POST["de-menu-columns"],
//                 "maintenance" => $_POST["de-menu-maintenance"]
//             );
//             echo 'DE Menu options saved';
//         }
////////////////////////////
?>
<div class="wrap">
<h2>DE Menu Plugin</h2>
<form method="post" action="<?php echo admin_url('options.php'); ?>">
    <?php settings_fields('de-menu-settings-group'); ?>
    <?php do_settings_sections('de-menu-options'); ?>
    <p class="submit">
    <input type="submit" name="de-menu-submit" value="Update Options" />
    </p>
</form>
</div>
<?php
}
public function settings_section_size_render() {
    echo '<p>' . __('Main description of this section here.','de-menu-lang') . '</p>';
}
public function w_render() {
 $w= esc_attr( get_option('de_w') );
 echo "<p><input name='de_w' value='$w'></p>\n";
}
public function h_render() {
 $h= esc_attr( get_option('de_h') );
 echo "<p><input name='de_h' value='$h'></p>\n";
}
public function width_height_render() {
 $width_height= get_option('de_width_height', array());
 $width= esc_attr( @$width_height['width'] );
 $height= esc_attr( @$width_height['height'] );
 echo "<p>Width: <input name='de_width_height[width]' value='$width'></p>\n";
 echo "<p>Height: <input name='de_width_height[height]' value='$height'></p>\n";
}
function validate_w($raw) {
 return (int)$raw;
}
function validate_h($raw) {
 return (int)$raw;
}
function validate_width_height($raw) {
 is_array($raw) or $raw= array();
 $result= array();
 $result['width']= (int)@$raw['width'];
 $result['height']= (int)@$raw['height'];
 return $result;
}
}
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.