设置API有哪些优势?

时间:2011-07-29 作者:stevendesu

让我先说一下,我几乎从未使用过WordPress——事实上,我上一次在WordPress中创建网站是在2.2版本。昨天我把一切都搞得一团糟,在这里问了几个问题,试图让一个基本的菜单插件正常工作。

现在,我的插件功能齐全,性能完全符合我的预期,所以我决定在这里和那里做一些小改动,以添加功能和兼容性,包括使用设置API。然而,在阅读关于这个API的教程的很短的时间内,我变得非常困惑,然后,当我继续阅读并尝试实现这些示例时,这种困惑加深了——由于我的插件是作为一个类实现的,这就更加困难了。

除非我做错了什么,根据我的理解,使用设置API需要为每个设置创建一个新函数。这意味着平均每个插件有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个)。

那么,我从这些额外的工作中获得了什么好处呢?

3 个回复
最合适的回答,由SO网友:Rarst 整理而成

我的观点是,设置API的主要目的和好处是structure.

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

有序(注册逻辑和章节)

所以您可以实现API设置所做的任何事情,而无需使用它。问题是,您能否以可靠、安全和可扩展的方式实现这一点。

SO网友:Chip Bennett

如果正确使用回调,就不需要所有冗余代码。Here\'s how I implement the Settings API, in a way that is completely scalable.

优势(除其他外):

设置API强制清理不受信任的用户数据

SO网友:kitchin

谢谢你发这个帖子,我也在想同样的事情。很多功能。

要减少它们,可以将选项存储为数组。Wordpress为您序列化数据。这样可以节省代码(或函数),但会产生更糟糕的数据。例如,如果要对表进行排序、手动编辑、导出等,它们将具有这些序列化的值。另一方面,您的插件向选项表中添加的条目更少,而且更容易清理。

下面是您的代码重做。注意事项:

我的示例演示了两个简单选项(de\\u w,de\\u h)和一个数组选项(de\\u width\\u height)<label> 便于访问。使用add\\u settings\\u error()、settings\\u error(),处理消息和错误。这通常是每个选项都有单独验证功能的唯一原因。您可以看到下面的validate\\u w()和validate\\u h()可以是一个函数。我试图抽象出消息,但我记得,您在验证回调中没有获得足够的信息。比如你在哪个领域工作代码:

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

结束