web-dev-qa-db-fra.com

Quels sont les avantages de l'API Settings?

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 au cours de 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 des centaines pour des 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 pouvez 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 quelque chose à gagner, 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 paramètres:

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

Les barres de défilement montrent clairement 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 une seule) afin d'accomplir tout cela.

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

12
stevendesu

Mon point de vue est que le but principal et l’avantage de l’API de paramètres est structure .

Il est utile de conserver des configurations complexes:

  • ordonné (logique d'enregistrement et sections);
  • sécurisé (rappels de validation, validation);
  • extensible (accrocher dans une autre page ou permettant d'être accroché).

Comme dans le cas de tels frais généraux structurels, cela profite à des cas d'utilisation plus complexes et à des 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.

8
Rarst

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

Avantages (entre autres):

  • L'API de paramètres force la suppression des données utilisateur non fiables.
  • L'API de configuration force 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 paramètres facilite l’interface utilisateur d’administrateur, qui est cohérente avec l’interface utilisateur principale d’administrateur, ce qui permet une meilleure expérience utilisateur.
5
Chip Bennett

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 elles sont plus faciles à nettoyer.

Alors, voici votre code refait. Quelques notes:

  • Mon exemple illustre à la fois des options simples (de_w, de_h) et une option de tableau (de_width_height).
  • Toujours désinfecter 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., lorsque vous utilisez l'API Settings.
  • La sauvegarde a lieu au chargement de la page suivante, pas à l’arrêt. Ensuite, WP effectue une redirection vers votre page. Pour déboguer, imprimez une sortie et appelez 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 le souhaitez.
  • 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é 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 tu travailles.
  • 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: $ c'est mieux que & $ 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;
}
}
0
kitchin