Quels sont les avantages de l'API de paramètres?

12

Permettez-moi de commencer par dire que je ne travaille presque jamais avec WordPress. En fait, la dernière fois que j'ai créé un site dans WordPress était de retour pendant la version 2.2. Hier, j'ai tout gâché et j'ai posé plusieurs questions ici pour essayer de faire fonctionner un plug-in de menu de base.

Le plug-in est maintenant entièrement fonctionnel et se comporte exactement comme je le souhaitais. J'ai donc décidé d'apporter des modifications mineures ici et là pour ajouter des fonctionnalités et une compatibilité, notamment à l'aide de l'API Settings. Cependant, un très court moment dans la lecture de tutoriels sur cette API et je suis devenu assez confus, puis cette confusion s’est aggravée au fur et à mesure que je lisais et essayais de mettre en œuvre les exemples - ce qui était rendu encore plus difficile par le fait que mon plugin était implémenté en tant que classe .

À moins que je ne fasse quelque chose de mal, ce que je comprends de l'utilisation de l'API de configuration nécessite la création d'une nouvelle fonction PER SETTING. Cela signifie 3 à 5 fonctions pour le plugin moyen et jusqu'à des centaines pour les plugins plus avancés. Il semble ridicule d’écrire autant de fonctions (et de développer un système de nommage pour ne pas les confondre), alors que vous pourriez tout aussi facilement importer toutes les variables $_POST applicables dans un tableau et renoncer à tout le désordre.

Je suis peut-être démodé, mais à moins d’obtenir un avantage, je ne vois pas pourquoi il faudrait tripler ou quadrupler la quantité de code que j’écris. Voici comment j'ai géré les options avant d'essayer d'ajouter l'API de configuration:

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

Maintenant, avec les paramètres de l'API, j'ai quelque chose de plus semblable à ce qui suit:

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

Il est probablement douloureusement évident aux barres de défilement que le code est déjà plus long avec seulement deux options. Les commentaires montrent clairement que je ne comprends pas tout à fait ce que je fais. Ensuite, il y a la question d'avoir 5 nouvelles fonctions (et d'en supprimer seulement une) afin d'accomplir tout cela.

Alors, quel avantage ai-je à tirer de tout ce travail supplémentaire?

    
posée stevendesu 29.07.2011 - 16:35

3 réponses

8

Mon point de vue est que l'objectif principal et les avantages de l'API de configuration sont la structure .

Il est utile de conserver les configurations complexes de paramètres:

  • orderly (logique d'enregistrement et sections);
  • secure (communications, rappels de validation);
  • extensible (accrochage dans une autre page ou possibilité d’être accroché).

Comme pour tous les frais généraux de structure, il est avantageux pour les cas d'utilisation plus complexes et pour les cas moins simples.

Vous pouvez donc implémenter tout ce que l'API de configuration fait sans l'utiliser. La question est de savoir si vous pouvez y parvenir de manière aussi fiable, sécurisée et extensible.

    
réponse donnée Rarst 29.07.2011 - 18:15
5

Si vous utilisez correctement les rappels, tout le code redondant n'est pas nécessaire. Voici comment j'implémente l'API des paramètres, de manière totalement évolutive .

Avantages (entre autres):

  • L'API de configuration force la suppression des données utilisateur non fiables.
  • L'API de configuration oblige les options à être enregistrées en tant que tableau d'options, générant une seule entrée de base de données wp_options, plutôt que des entrées de base de données discrètes pour chaque option
  • L’API de configuration facilite le renforcement de la sécurité du formulaire de configuration
  • L'API de configuration simplifie la cohérence de l'interface utilisateur d'administration avec l'interface utilisateur principale de l'administrateur, permettant ainsi une meilleure expérience utilisateur
réponse donnée Chip Bennett 29.07.2011 - 17:45
0

Merci d'avoir posté ceci, je me demandais exactement la même chose. Beaucoup de fonctions.

Pour les réduire, vous pouvez stocker vos options sous forme de tableaux. Wordpress sérialise les données pour vous. Cela économise du code (ou fonctionne de toute façon), mais rend les données plus mauvaises. Par exemple, si vous voulez trier, éditer à la main, exporter, etc., vos tables, elles auront ces valeurs sérialisées. D'autre part, votre plugin ajoute moins d'entrées à la table d'options et il est plus facile de les nettoyer.

Alors, voici votre code refait. Quelques notes:

  • Mon exemple présente à la fois des options simples (de_w, de_h) et une option de tableau (de_width_height).
  • Toujours nettoyer les entrées de l'utilisateur. J'ai utilisé des nombres entiers dans l'exemple car ils sont faciles à désinfecter.
  • Vous n’avez pas besoin de $ _POST, nonces, check_admin_referer (), update_option (), etc. lors de l’utilisation de l’API Paramètres.
  • La sauvegarde a lieu au chargement de la page suivante, pas à l’arrêt. Ensuite, WP effectue une redirection vers votre page. Donc, pour déboguer, imprimer une sortie et appeler wp_die () dans l’une des fonctions de validation.
  • L'action de formulaire est toujours "options.php". C'est ainsi que fonctionne l'API de configuration. N'utilisez rien d'autre. Eh bien, vous pouvez utiliser admin_url ('options.php') si vous voulez.
  • WP imprimera le message de sauvegarde pour vous.
  • Améliorations non incluses ici: utilisation de <label> pour l'accessibilité. Utilisation de add_settings_error (), settings_error (), qui gère les messages ainsi que les erreurs. C'est souvent la seule raison d'avoir des fonctions de validation distinctes pour chaque option. Vous pouvez voir ci-dessous validate_w () et validate_h () pourraient être une fonction. J'ai essayé d'essayer de résumer le message, mais vous ne recevez pas assez d'informations dans le rappel de validation, si je me souviens bien. Comme dans quel domaine vous travaillez.
  • Les fonctions de rappel de validation obtiennent une valeur brute $ _POST de l'API Settings. J'aime nommer le paramètre en tant que tel, $ raw. Pour l'option tableau, vous obtenez un tableau, comme par magie.
  • Edit: $ this est meilleur que & amp this $.

Code:

<?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;
}
}
    
réponse donnée kitchin 14.12.2013 - 16:14

Lire d'autres questions sur les étiquettes