Quais são as vantagens para a API de configurações?

12

Deixe-me começar dizendo que quase nunca trabalho com o WordPress - na verdade, a última vez que eu fiz um site no WordPress estava de volta durante o 2.2. Ontem eu fiz uma grande bagunça de tudo e fiz várias perguntas aqui tentando fazer com que um plugin de menu básico funcionasse.

Agora tenho o plug-in totalmente funcional e me comportando exatamente como esperado, por isso decidi fazer pequenas alterações aqui e ali para adicionar funcionalidade e compatibilidade, inclusive usando a API de configurações. No entanto, um momento muito curto para ler tutoriais sobre esta API e fiquei bastante confuso, então essa confusão só se aprofundou quando eu li e tentei implementar os exemplos - o que se tornou ainda mais difícil pelo fato de meu plugin ser implementado como uma classe .

A menos que eu esteja fazendo algo errado, pelo que entendi para usar a API de configurações, é necessário criar uma nova função PER SETTING. Isso significa 3-5 funções para o plug-in médio e até centenas para plug-ins mais avançados. Parece ridículo escrever essas muitas funções (e desenvolver um sistema de nomes para evitar confundi-las) quando você poderia facilmente importar todas as variáveis $_POST aplicáveis em uma matriz e abandonar toda a confusão.

Talvez eu seja antiquado, mas a menos que haja algo a ganhar com isso, não vejo razão para triplicar ou quadruplicar a quantidade de código que estou escrevendo. Veja como gerenciei opções antes de tentar adicionar a API de configurações:

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

Agora, com a API de configurações, tenho algo mais parecido com o seguinte:

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

Provavelmente é dolorosamente óbvio nas barras de rolagem que o código já é mais longo com apenas duas opções. É óbvio, pelos comentários, que eu não entendo completamente o que estou fazendo. Depois, há a questão de ter 5 novas funções (e remover apenas 1) para realizar tudo isso.

Então, que vantagem eu estou ganhando com todo esse trabalho extra?

    
por stevendesu 29.07.2011 / 16:35

3 respostas

8

Meu ponto de vista é que o principal objetivo e benefício da API de configurações é a estrutura .

Ajuda a manter configurações de configurações complexas:

  • ordenada (lógica de registro e seções);
  • seguro (nonces, callbacks de validação);
  • extensível (conectando-se a outra página ou permitindo a conexão).

Como acontece com qualquer sobrecarga estrutural, ela beneficia casos de uso mais complexos e beneficia os menos simples.

Assim, você pode implementar qualquer coisa que a API de configurações faça sem usá-la. A questão é se você pode conseguir isso de maneira confiável, segura e extensível.

    
por Rarst 29.07.2011 / 18:15
5

Se você usar callbacks corretamente, não há necessidade de todo o código redundante. Veja como eu implemento a API de configurações, de uma maneira totalmente escalonável .

Vantagens (entre outras coisas):

  • A API de configurações força a limpeza de dados do usuário não confiáveis.
  • A API de configurações força as opções a serem registradas como uma matriz de opções, resultando em uma única entrada de banco de dados wp_options, em vez de entradas de banco de dados separadas para cada opção
  • A API de configurações facilita o fortalecimento da segurança do formulário de configurações
  • A API de configurações facilita a interface do usuário do administrador de maneira consistente com a interface do usuário central do administrador, resultando em melhor UX
por Chip Bennett 29.07.2011 / 17:45
0

Obrigado por postar isso, eu queria saber exatamente a mesma coisa. Muitas funções.

Para reduzi-los, você pode armazenar suas opções como matrizes. Wordpress serializa os dados para você. Isso economiza código (ou funciona de qualquer maneira), mas piora os dados. Por exemplo, se você quiser classificar, editar manualmente, exportar, etc., suas tabelas, elas terão esses valores serializados. Por outro lado, o seu plugin adiciona menos entradas à tabela de opções e é mais fácil de limpar.

Então aqui está seu código refeito. Algumas notas:

  • Meu exemplo demonstra as opções simples (de_w, de_h) e uma opção de matriz (de_width_height).
  • Sempre limpe a entrada do usuário. Eu usei inteiros no exemplo porque eles são fáceis de higienizar.
  • Você não precisa de $ _POST, nonces, check_admin_referer (), update_option (), etc., ao usar a API de configurações.
  • O salvamento acontece no próximo carregamento da página, não no encerramento. Então o WP faz um redirecionamento para sua página. Então, para depurar, imprima alguma saída e chame wp_die () em uma das funções de validação.
  • A ação do formulário é sempre "options.php". É assim que funciona a API de configurações. Não use mais nada. Bem, você pode usar admin_url ('options.php') se quiser.
  • WP imprimirá a mensagem de salvamento para você.
  • Aprimoramentos não incluídos aqui: usando <label> para acessibilidade. Usando add_settings_error (), settings_error (), que manipula mensagens e erros. Essa é frequentemente a única razão para ter funções de validação separadas para cada opção. Você pode ver abaixo validate_w () e validate_h () pode ser uma função. Eu olhei para tentar abstrair a mensagem, mas você não consegue informações suficientes no retorno de chamada de validação, como me recordo. Como em qual campo você está trabalhando.
  • As funções de retorno de chamada de validação obtêm um valor bruto $ _POST na API de configurações. Eu gosto de nomear o parâmetro como tal, $ raw. Para a opção de matriz, você obtém uma matriz, como mágica.
  • Editar: $ isso é melhor que & $ isso.

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