设置API有什么优势?


13

首先,我要说我几乎不使用WordPress,实际上,我最后一次在WordPress中创建网站是在2.2期间。昨天我把所有东西弄得一团糟,在这里问了几个问题,试图使基本的菜单插件正常工作。

现在,我的插件可以正常运行,并且性能完全符合我的预期,因此我决定在此进行一些小的更改以增加功能和兼容性-包括使用Settings API。但是,阅读此API教程的时间很短,我感到非常困惑,然后,当我继续阅读并尝试实现示例时,这种困惑就加深了-由于我的插件被实现为类,这变得更加困难。

除非我做错了事,否则据我所知,要使用Settings API,需要创建一个新的功能PER SETTING。这意味着平均每个插件需要3-5个功能,而更多高级插件则需要多达数百个功能。当您可以很容易地将所有适用的$_POST变量导入数组并放弃整个混乱时,编写这么多函数(开发一个命名系统以免混淆)似乎很荒谬。

也许我是过时的,但是除非能从中受益,否则我看不出将我编写的代码增加三倍或四倍的原因。这是在尝试添加Settings 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来编写所有内容,这完全取决于您的使用方式,请注意,即使不使用add_settings_section和也可以使用API add_settings_field,这两个函数比任何东西都给代码增加了膨胀,避免了这些,并且避免了膨胀。
t31os 2011年

1
我做的和t3los一样:注册设置本身,然后在设置页面上以HTML格式在表单中进行编码。如果您希望看到一种非常简单的方法来保存代码以备后用,请查看Yoast的WordPress SEO插件。
chrisguitarguy 2011年

Answers:


8

我的观点是Settings API的主要目的和好处是结构

它有助于保持复杂的设置设置:

  • 有秩序的(注册和部分的逻辑);
  • 安全(随机数,验证回调);
  • 可扩展的(挂钩到另一个页面或允许被挂钩)。

与任何此类结构性开销一样,它使更复杂的用例受益,而对简单情况则不那么有利。

因此,您确实可以实现设置API不需要执行的任何操作。问题是您是否可以以可靠,安全和可扩展的方式完成此任务。


我终于在“设置”页面上获得了本教程的帮助:alisothegeek.com/2011/01/wordpress-settings-api-tutorial-1并借助switch语句和帮助器功能,我必须说,现在事情变得更加有序了在我的代码中(这很好,因为我计划从两个测试设置迁移到15-20个总设置)。
stevendesu 2011年

1
@steven_desu是的,开玩笑的是每个使用Settings API的人都为此编写了一个框架。:)夫妇辅助功能几乎是不可避免的。另请注意,Settings API尚未完成,并且有(模糊)计划在将来进行改进(我认为在3.3计划中已提及)。
罗斯特2011年

1
我当然希望它有所改善。老实说,我认为Settings API没有任何优势,但是我现在享受的每一项优势都是我为此借用的框架的结果。我喜欢现在所有表单元素都以相同的外观动态生成...但这不是Settings API。我喜欢默认设置和注册设置由相同的定义来处理...但这不是Settings API。我喜欢jQuery,不仅使表单漂亮,而且逐步增强-但我不得不手动编写逐步增强的代码……
stevendesu 2011年

5

如果正确使用回调,则不需要所有冗余代码。这是我以完全可扩展的方式实现Settings API的方法

优势(除其他外):

  • 设置API强制清除不受信任的用户数据。
  • Settings API强制将选项注册为选项数组,从而产生单个wp_options数据库条目,而不是每个选项的离散数据库条目
  • 设置API有助于加强设置表单的安全性
  • 设置API有助于使管理界面与核心管理界面一致,从而带来更好的用户体验

因此,它实际上迫使我在没有帮助的情况下一直遵循的安全性和美学标准吗?不过,我将通读您链接的教程。如果它使Settings API像手动编码表单一样容易(或更容易),那么我将接受这个答案
stevendesu 2011年

您是否知道指向的源代码实现了这些功能oenology_get_settings_by_tab()oenology_get_default_options而没有先定义它们?我认为这对于209行代码(在删除注释和空白行之后)已经够糟糕的了,但是一旦定义了这些功能,它甚至会更长……对于四个选项?
stevendesu 2011年

它们在其他地方定义。该oenology_get_settings_by_tab()不是你在做什么真正相关。但是,您必须某个地方定义表单域标记,就像您必须某种方式验证/清除用户输入一样,因此,如果操作正确,则也将具有所有相同的代码。
Chip Bennett

0

感谢您发布此信息,我想知道完全相同的事情。很多功能。

为了减少它们,您可以将选项存储为数组。Wordpress为您序列化数据。这样可以节省代码(或仍然保持功能),但会使数据更糟。例如,如果您想对表进行排序,手动编辑,导出等操作,则它们将具有这些序列化的值。另一方面,您的插件将较少的条目添加到选项表,并且它们更易于清理。

所以这是您的代码重做。一些注意事项:

  • 我的示例演示了简单选项(de_w,de_h)和数组选项(de_width_height)。
  • 始终清理用户输入。我在示例中使用了整数,因为它们很容易清理。
  • 使用设置API时,不需要$ _POST,nonce,check_admin_referer(),update_option()等。
  • 保存发生在下一页加载时,而不是关闭时。然后WP重定向到您的页面。因此,要调试,请打印一些输出,然后在其中一个验证函数中调用wp_die()。
  • 表单操作始终为“ options.php”。这就是Settings API的工作方式。不要使用其他任何东西。好吧,如果需要,您可以使用admin_url('options.php')。
  • WP将为您打印保存消息。
  • 此处未包括的增强功能:<label>用于辅助功能。使用add_settings_error()和settings_error()来处理消息和错误。这通常是每个选项都具有单独的验证功能的唯一原因。您可以在下面看到validate_w()和validate_h()可能是一个函数。我看过试图抽象出消息传递,但是我记得您在验证回调中没有得到足够的信息。像您正在从事的领域。
  • 验证回调函数从Settings API获取原始的$ _POST值。我喜欢这样命名参数$ raw。对于array选项,您将获得一个数组,例如魔术。
  • 编辑:$ this比&$ this更好。

码:

<?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;
}
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.