Які переваги в API налаштувань?


13

Дозвольте мені передмовити це, сказавши, що я навряд чи коли-небудь працюю з WordPress - насправді, востаннє, коли я робив сайт у WordPress, повертався протягом 2.2. Вчора я заплутався у всьому, і задав тут кілька запитань, намагаючись зробити базовий плагін меню робочим.

Тепер у мене плагін повністю функціонує і поводиться точно так, як я очікував, тому я вирішив внести незначні зміни тут і там, щоб додати функціональність та сумісність - включаючи використання API налаштувань. Однак дуже короткий момент, коли я читав підручники з цього API, і я дуже заплутався, тоді ця плутанина лише поглибилась, коли я читав і намагався реалізувати приклади - що було ще складніше через те, що мій плагін реалізований як клас .

Якщо я не роблю щось не так, з того, що я розумію, використовувати API Settings, потрібно створити нову функцію PER SETTING. Це означає 3-5 функцій для середнього плагіна і до сотні для більш розвинених плагінів. Дуже смішно писати це багато функцій (і розробити систему імен, щоб не заплутати їх), коли ви могли так само легко імпортувати всі застосовні $_POSTзмінні в масив і відмовитися від усього безладу.

Можливо, я старомодний, але, якщо від цього є що отримати, я не бачу приводу втричі чи вчетверо, скільки коду я пишу. Ось як я керував параметрами перед спробою додати API налаштувань:

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

Тепер у API налаштувань у мене є щось на кшталт наступного:

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

З прокрутки, мабуть, болісно очевидно, що код вже довший із лише двома варіантами. З коментарів це очевидно, що я не зовсім розумію, що роблю. Тоді справа в тому, щоб мати 5 нових функцій (і видалити лише 1) для виконання всього цього.

Тож яку перевагу я отримую від усієї цієї додаткової роботи?


Не використовуйте їх у таких випадках. Я думаю, що вони призначені для початківців PHP, яким потрібно 3-4 варіанти всередині свого плагіна / теми. Це одна з "функцій", яка ніколи не повинна була бути реалізована ... Це в основному API для іншого API :)
onetrickpony

3
Я використовую API налаштувань для всього, що я пишу, все залежить від того, як ви його використовуєте, зауважте, ви можете користуватися API навіть без використання, add_settings_sectionі add_settings_fieldці дві функції додають коду до вашого коду більше, ніж нічого, уникайте цих, і ви уникаєте роздуття ..
t31os

1
Я роблю те ж саме, що і t3los: реєструю сам параметр, а потім просто кодую форми у HTML на моїй сторінці налаштувань. Якщо ви хочете побачити дійсно простий спосіб зробити це і зберегти код на потім, перегляньте SEO-плагін Yoast's WordPress SEO.
chrisguitarguy

Відповіді:


8

Моя точка зору полягає в тому, що основна мета та перевага API налаштувань - це структура .

Це допомагає зберегти складні налаштування:

  • впорядкованість (логіка реєстрації та розділів);
  • захищеність (не має значення, зворотне підтвердження викликів);
  • розширюваний (приєднання до іншої сторінки або дозволяє приєднатися до неї).

Як і у будь-яких подібних структурних накладних витрат, це виграє складніші випадки використання та вигоди менш прості.

Таким чином, ви можете реалізувати все, що API API робить, не використовуючи його. Питання полягає в тому, чи можете ви зробити це максимально надійним, безпечним та розширеним способом.


Нарешті я перетворив свою сторінку "Налаштування" за допомогою цього підручника: alisothegeek.com/2011/01/wordpress-settings-api-tutorial-1 і за допомогою операторів перемикання та допоміжних функцій я мушу сказати, що тепер справи впорядкованіші. в моєму коді (що приємно, оскільки я планую перейти від двох моїх тестових налаштувань до 15-20 загальних налаштувань).
stevendesu

1
@steven_desu так, жарт полягає в тому, що кожен, хто використовує API налаштувань, пише для цього рамки. :) Пара допоміжних функцій майже неминуча. Також зауважте, що API налаштувань не вважається доопрацьованим, і є (невиразні) плани щодо його вдосконалення в майбутньому (я думаю, він згадувався в контексті 3.3 планів).
Рарст

1
Я звичайно сподіваюся, що це покращиться Я, чесно кажучи, не бачу переваг API налаштувань, але, скоріше, кожна перевага, якою мені зараз подобається, є результатом рамки, яку я запозичив. Мені подобається, що всі елементи форми тепер динамічно генеруються з однаковим виглядом ... але це не API налаштувань. Мені подобається, що налаштування за замовчуванням і параметри реєстрації обробляються тими ж визначеннями ... але це не API налаштувань. Мені подобається, що jQuery не тільки робить форми гарними, але й прогресивно вдосконалюється - але мені довелося вручну
кодувати

5

Якщо ви правильно користуєтеся зворотними дзвінками, не потрібен весь зайвий код. Ось як я реалізую API налаштувань таким чином, що є повністю масштабованим .

Переваги (серед іншого):

  • API налаштування змушує проводити дезіннізацію ненадійних даних користувачів.
  • API налаштування змушує параметри реєструватись як масив параметрів, що призводить до отримання одного запису DB wp_options, а не дискретних записів БД для кожного параметра
  • API налаштувань полегшує безпеку зміцнення форми налаштувань
  • API налаштування полегшує користувальницький інтерфейс адміністратора, що відповідає основним інтерфейсам адміністратора, в результаті чого покращує UX

Отже, це по суті змушує стандарти безпеки та естетичні норми, яких я вже дотримувався без його допомоги? Я перечитаю підручник, який ви пов’язали. Якщо це робить API налаштувань таким же простим, як кодування форм вручну (або простіше), я прийму цю відповідь
stevendesu

Чи знаєте ви, що вихідний код, на який ви вказали, реалізує функції oenology_get_settings_by_tab()та oenology_get_default_optionsне вперше визначає їх? Я вважав, що це досить погано в 209 рядках коду (після видалення коментарів та порожніх рядків), але як тільки ці функції будуть визначені, це буде ще довше ... Для чотирьох варіантів?
stevendesu

Вони визначені в іншому місці. oenology_get_settings_by_tab()Не зовсім відповідає тому , що ви робите. Але ви повинні де-небудь визначити свою розмітку поля форми , як і вам потрібно якось перевірити / оздоровити введення користувача , так що якщо ви зробите це правильно, ви будете мати і той самий код.
Чіп Беннетт

0

Дякую за повідомлення про це, мені було цікаво саме те саме. Багато функцій.

Щоб зменшити їх, ви можете зберігати свої параметри як масиви. Wordpress серіалізує дані для вас. Це економить на коді (або функціонує в будь-якому випадку), але робить гірші дані. Наприклад, якщо ви хочете сортувати, вручну редагувати, експортувати тощо ваші таблиці, вони матимуть ці серіалізовані значення. З іншого боку, ваш плагін додає менше записів до таблиці параметрів, і їх простіше очистити.

Тож ось ваш код знову зроблено. Кілька приміток:

  • Мій приклад демонструє як прості параметри (de_w, de_h), так і параметр масиву (de_width_height).
  • Завжди саніруйте введення користувачів. Я використовував цілі числа в прикладі, тому що їх легко дезінфікувати.
  • Вам не потрібен $ _POST, значить, check_admin_referer (), update_option () тощо при використанні API налаштувань.
  • Збереження відбувається при завантаженні наступної сторінки, а не при закритті. Тоді WP робить переадресацію на вашу сторінку. Тож для налагодження надрукуйте деякий вихід та зателефонуйте wp_die () в одну з функцій перевірки.
  • Дія форми завжди є "options.php." Саме так працює API налаштувань. Нічого іншого не використовуйте. Ну, ви можете використовувати admin_url ('options.php'), якщо хочете.
  • WP надрукує повідомлення про збереження для вас.
  • Тут не включені удосконалення: використання <label>для доступності. Використання add_settings_error (), settings_error (), які обробляють повідомлення, а також помилки. Це часто єдина причина мати окремі функції перевірки для кожної опції. Нижче ви бачите validate_w (), а validate_h () може бути однією функцією. Я розглядав спробу абстрагувати повідомлення, але, як я пам'ятаю, ви не отримуєте достатньої кількості інформації про зворотний виклик перевірки. Як і в якому полі ви працюєте.
  • Функції зворотного виклику перевірки отримують необмежене значення $ _POST з API налаштувань. Я люблю називати параметр таким, $ raw. Для параметра масиву ви отримуєте масив, як магія.
  • Редагувати: $ це краще, ніж & $ це.

Код:

<?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;
}
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.