¿Cuáles son las ventajas de la API de configuración?

12

Permítanme comenzar con esto diciendo que casi nunca trabajo con WordPress; de hecho, la última vez que hice un sitio en WordPress fue en 2.2. Ayer hice todo un lío de todo e hice varias preguntas aquí intentando que funcionara un complemento de menú básico.

Ahora tengo el complemento totalmente funcional y se comporta exactamente como lo esperaba, así que decidí hacer pequeños cambios aquí y allá para agregar funcionalidad y compatibilidad, incluido el uso de la API de configuración. Sin embargo, un momento muy breve para leer tutoriales sobre esta API y me confundí bastante, entonces esta confusión solo se profundizó a medida que seguí leyendo e intenté implementar los ejemplos, lo que se hizo aún más difícil por el hecho de que mi complemento se implementa como una clase .

A menos que esté haciendo algo mal, por lo que entiendo para usar la API de configuración, se requiere la creación de una nueva función POR CONFIGURACIÓN. Esto significa 3-5 funciones para el complemento promedio, y hasta cientos para complementos más avanzados. Parece ridículo escribir tantas funciones (y desarrollar un sistema de nombres para no confundirlas) cuando podría importar fácilmente todas las variables $_POST aplicables en una matriz y renunciar a todo el lío.

Tal vez sea anticuado, pero a menos que tenga algo que ganar, no veo la razón para triplicar o cuadruplicar la cantidad de código que estoy escribiendo. Así es como administré las opciones antes de intentar agregar la API de configuración:

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

Ahora con la configuración API tengo algo más como lo siguiente:

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

Es probable que sea dolorosamente obvio por las barras de desplazamiento que el código ya es más largo con solo dos opciones. Es bastante obvio por los comentarios que no entiendo completamente lo que estoy haciendo. Luego está la cuestión de tener 5 funciones nuevas (y eliminar solo 1) para lograr todo esto.

Entonces, ¿qué ventaja estoy obteniendo de todo este trabajo adicional?

    
pregunta stevendesu 29.07.2011 - 16:35

3 respuestas

8

Mi punto de vista es que el propósito principal y el beneficio de la API de configuración es estructura .

Ayuda mantener configuraciones de configuraciones complejas:

  • ordenado (lógica de registro y secciones);
  • seguro (nonces, devoluciones de llamada de validación);
  • extensible (enganchar en otra página o permitir que se enganche en).

Como con cualquier sobrecarga estructural, beneficia casos de uso más complejos y beneficia a los menos simples.

Así que puedes implementar cualquier cosa que la API de configuración haga sin usarla. La pregunta es si puede lograrlo de manera confiable, segura y extensible.

    
respondido por el Rarst 29.07.2011 - 18:15
5

Si utiliza las devoluciones de llamada correctamente, no hay necesidad de todo el código redundante. Aquí es cómo implemento la API de configuración, de una manera que es completamente escalable .

Ventajas (entre otras cosas):

  • La API de configuración obliga a limpiar los datos de los usuarios que no son de confianza.
  • La API de configuración obliga a que las opciones se registren como una matriz de opciones, lo que da como resultado una sola entrada de base de datos wp_options, en lugar de entradas de base de datos discretas para cada opción
  • La API de configuración facilita el fortalecimiento de la seguridad del formulario de configuración
  • La API de configuración facilita la IU de administración de forma coherente con la IU de administración del núcleo, lo que se traduce en una mejor UX
respondido por el Chip Bennett 29.07.2011 - 17:45
0

Gracias por publicar esto, me estaba preguntando exactamente lo mismo. Muchas funciones.

Para reducirlos puede almacenar sus opciones como matrices. Wordpress serializa los datos por ti. Esto guarda en el código (o funciones de todos modos), pero hace peor los datos. Por ejemplo, si desea ordenar, editar manualmente, exportar, etc., sus tablas, tendrán estos valores serializados. Por otro lado, su complemento agrega menos entradas a la tabla de opciones y son más fáciles de limpiar.

Así que aquí está su código re-hecho. Algunas notas:

  • Mi ejemplo muestra las opciones simples (de_w, de_h) y una opción de matriz (de_width_height).
  • Siempre desinfectar la entrada del usuario. Utilicé enteros en el ejemplo porque son fáciles de desinfectar.
  • No necesita $ _POST, nonces, check_admin_referer (), update_option (), etc., cuando usa la API de configuración.
  • El guardado ocurre en la carga de la página siguiente, no en el cierre. Entonces WP hace una redirección a su página. Entonces, para depurar, imprima algunos resultados y llame a wp_die () en una de las funciones de validación.
  • La acción de formulario siempre es "options.php". Así es como funciona la API de configuración. No uses nada más. Bueno, puedes usar admin_url ('options.php') si quieres.
  • WP imprimirá el mensaje guardado por ti.
  • Mejoras no incluidas aquí: usar <label> para accesibilidad. Usando add_settings_error (), settings_error (), que maneja mensajes y errores. Esa es a menudo la única razón para tener funciones de validación separadas para cada opción. Puede ver más abajo validate_w () y validate_h () podría ser una función. Miré tratando de abstraer el mensaje, pero no tengo suficiente información en la devolución de llamada de validación, según recuerdo. Me gusta en qué campo estás trabajando.
  • Las funciones de devolución de llamada de validación obtienen un valor $ _POST sin formato de la API de configuración. Me gusta nombrar el parámetro como tal, $ raw. Para la opción de matriz, obtienes una matriz, como magia.
  • Editar: $ esto es mejor que & $ esto.

Código:

<?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;
}
}
    
respondido por el kitchin 14.12.2013 - 16:14

Lea otras preguntas en las etiquetas