让我先说一下,我几乎从未使用过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个)。
那么,我从这些额外的工作中获得了什么好处呢?
SO网友:kitchin
谢谢你发这个帖子,我也在想同样的事情。很多功能。
要减少它们,可以将选项存储为数组。Wordpress为您序列化数据。这样可以节省代码(或函数),但会产生更糟糕的数据。例如,如果要对表进行排序、手动编辑、导出等,它们将具有这些序列化的值。另一方面,您的插件向选项表中添加的条目更少,而且更容易清理。
下面是您的代码重做。注意事项:
我的示例演示了两个简单选项(de\\u w,de\\u h)和一个数组选项(de\\u width\\u height)始终清理用户输入。我在示例中使用了整数,因为它们很容易清理使用设置API时,不需要$\\u POST、nonces、check\\u admin\\u referer()、update\\u option()等保存发生在下一页加载时,而不是关机时。然后WP重定向到您的页面。因此,要进行调试,请打印一些输出并在其中一个验证函数中调用wp\\u die()表单操作始终是“options.php”这就是设置API的工作方式。不要使用其他任何东西。如果需要,可以使用admin\\uURL(\'options.php\')<label> 便于访问。使用add\\u settings\\u error()、settings\\u error(),处理消息和错误。这通常是每个选项都有单独验证功能的唯一原因。您可以看到下面的validate\\u w()和validate\\u h()可以是一个函数。我试图抽象出消息,但我记得,您在验证回调中没有获得足够的信息。比如你在哪个领域工作验证回调函数从设置API获取原始$\\u POST值。我喜欢将参数命名为$raw。对于数组选项,您可以得到一个数组,就像magic一样编辑:$这比&$这个代码:
<?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;
}
}