我正在努力让用WordPress设置API创建的选项卡式插件设置正常工作。
第一个选项卡正确保存设置。但是,每次我单击任何其他选项卡的“保存更改”按钮时,都会出现一个白色屏幕,其中显示以下错误:
错误:找不到选项页
Chrome和Apache日志显示POST 500错误。我发现要提交的表单数据似乎是正确的,并且符合为第一个有效选项卡提交的内容general_section
:
option_page: account_section
action: update
_wpnonce: 2d40b0a357
_wp_http_referer: /staging/wp-admin/options-general.php?page=woo-extra-settings&tab=account
eswc_settingz[eswc_redirect]: 1
submit: Save Changes
只有选择了正确的选项卡,才能注册这些字段,以避免在保存时将其他选项卡中的值重置为默认值。
本主题中的代码包含在我的示例中,但没有解决问题:
"Error: Options Page Not Found" on Settings Page Submission for an OOP Plugin
我为Chrome使用PHP控制台扩展,并使用插件将值打印到Chrome控制台以进行故障排除,例如:
PC::debug( \'general\', \'tab name\' );
现在对此进行了评论。该代码可以作为我插件的一部分,在默认的“设置”菜单中生成一个两个选项卡的设置页面,并重现我遇到的问题。
在选项卡激活时,控制台返回以下值(whitelist_custom_options_page
函数不执行):
“常规”(第一个选项卡):
tab name: general
add settings section - page: woo-extra-settings
add settings section - id: general_section
“账户”(第二个选项卡)
tab name: account
add settings section - page: woo-extra-settings
add settings section - id: account_section
保存设置时,值为:
“常规”(第一个选项卡):
tab name: general
add settings section - page: woo-extra-settings
add settings section - id: general_section
whitelist page: woo-extra-settings
whitelist section: general_section
whitelist option: eswc_settingz
对于“Account”(第二个选项卡),值都是相同的,这意味着在保存设置时,我的代码错误地将任何选项卡视为第一个选项卡,我遇到问题的原因是什么。
如何以接近当前实现的方式解决此问题?
代码如下:
class extra_settings_settings {
private $options;
private $settings_page_name;
private $settings_menu_name;
public function __construct() {
if ( is_admin() ) {
$this->settings_page_name = \'woo-extra-settings\';
$this->settings_menu_name = \'Woo Extra Settings\';
// Tracks new sections for whitelist_custom_options_page()
$this->page_sections = array();
// Must run after option_update_filter(), so priority > 10
add_action( \'whitelist_options\', array( $this, \'whitelist_custom_options_page\' ),11 );
// Initialize and register settings.
add_action( \'admin_init\', array( $this, \'display_options\' ) );
// Add settings page.
add_action( \'admin_menu\', array( $this, \'add_settings_page\' ) );
}
}
public function display_options() {
$active_tab = isset( $_GET[ \'tab\' ] ) ? $_GET[ \'tab\' ] : \'general\';
if ( $active_tab == \'general\' ) {
//PC::debug( \'general\', \'tab name:\' );
register_setting( \'general_section\', \'eswc_settingz\', array( $this, \'sanitize_general\' ) );
// ID / title / cb / page
$this->add_settings_section( \'general_section\', null, array( $this, \'general_section_cb\' ), $this->settings_page_name );
// ID / title / cb / page / section /args
add_settings_field( \'eswc_kill_gutenberg\', __( \'Gutenberg\', \'extra-settings-for-woocommerce\' ), array( $this, \'eswc_kill_gutenberg_cb\' ), $this->settings_page_name, \'general_section\' );
add_settings_field( \'eswc_change_email_author\', __( \'WP core email author\', \'extra-settings-for-woocommerce\' ), array( $this, \'eswc_change_email_author_cb\' ), $this->settings_page_name, \'general_section\' );
} else if ( $active_tab == \'account\' ) {
//PC::debug( \'account\', \'tab name:\' );
register_setting( \'account_section\', \'eswc_settingz\', array( $this, \'sanitize_account\' ) );
$this->add_settings_section( \'account_section\', null, array( $this, \'account_section_cb\' ), $this->settings_page_name );
add_settings_field( \'eswc_redirect\', __( \'Login redirect\', \'extra-settings-for-woocommerce\' ), array( $this, \'eswc_redirect_cb\' ), $this->settings_page_name, \'account_section\' );
}
}
public function add_settings_page() {
// This page will be under "Settings"
$this->plugin_hook_suffix = add_options_page(
\'Settings Admin\', $this->settings_menu_name, \'manage_options\', $this->settings_page_name, array( $this, \'create_settings_page\' )
);
}
// Wrapper for wp\'s `add_settings_section()` that tracks custom sections
private function add_settings_section( $id, $title, $cb, $page ){
add_settings_section( $id, $title, $cb, $page );
if( $id != $page ){
if( !isset($this->page_sections[$page]))
//PC::debug( $page, \'add settings section - page:\' );
//PC::debug( $id, \'add settings section - id:\' );
$this->page_sections[$page] = array();
$this->page_sections[$page][$id] = $id;
}
}
// White-lists options on custom pages.
public function whitelist_custom_options_page( $whitelist_options ){
// Custom options are mapped by section id; Re-map by page slug.
foreach($this->page_sections as $page => $sections ){
//PC::debug( $page, \'whitelist page:\' );
$whitelist_options[$page] = array();
foreach( $sections as $section )
//PC::debug( $section, \'whitelist section:\' );
if( !empty( $whitelist_options[$section] ) )
foreach( $whitelist_options[$section] as $option )
$whitelist_options[$page][] = $option;
//PC::debug( $option, \'whitelist option:\' );
}
return $whitelist_options;
}
/**
* Get the option that is saved or the default.
*
* @param string $index. The option we want to get.
*/
public function eswc_get_settings( $index = false ) {
$defaults = array ( \'eswc_kill_gutenberg\' => false, \'eswc_change_email_author\' => false, \'eswc_redirect\' => false);
$settings = get_option( \'eswc_settingz\', $defaults );
if ( $index && isset( $settings[ $index ] ) ) {
return $settings[ $index ];
}
return $settings;
}
public function create_settings_page() {
$this->options = $this->eswc_get_settings();
?>
<div class="wrap">
<h1>Extra Settings For WooCommerce</h1>
<?php
$active_tab = isset( $_GET[ \'tab\' ] ) ? $_GET[ \'tab\' ] : \'general\';
?>
<h2 class="nav-tab-wrapper">
<a href="?page=woo-extra-settings&tab=general" class="nav-tab <?php echo $active_tab == \'general\' ? \'nav-tab-active\' : \'\'; ?>">General</a>
<a href="?page=woo-extra-settings&tab=account" class="nav-tab <?php echo $active_tab == \'account\' ? \'nav-tab-active\' : \'\'; ?>">Account</a>
<form method="post" action="options.php">
<?php
// Output nonce, action, and option_page fields for a settings page.
if( $active_tab == \'general\' ) {
settings_fields( \'general_section\' );
echo \'<table class="form-table">\';
do_settings_fields ($this->settings_page_name, \'general_section\');
echo \'</table>\';
} else if ( $active_tab == \'account\' ){
settings_fields( \'account_section\' );
echo \'<table class="form-table">\';
do_settings_fields ($this->settings_page_name, \'account_section\');
echo \'</table>\';
}
submit_button();
?>
</form>
</div>
<?php
}
/**
* Sanitize each setting field as needed
*
* @param array $input Contains all settings fields as array keys
*/
public function sanitize_general( $input ) {
$new_input = array();
if( isset( $input[\'eswc_kill_gutenberg\'] ) )
$new_input[\'eswc_kill_gutenberg\'] = ( $input[\'eswc_kill_gutenberg\'] == 1 ? 1 : 0 );
if( isset( $input[\'eswc_change_email_author\'] ) )
$new_input[\'eswc_change_email_author\'] = ( $input[\'eswc_change_email_author\'] == 1 ? 1 : 0 );
return $new_input;
}
public function sanitize_account( $input ) {
$new_input = array();
if( isset( $input[\'eswc_redirect\'] ) )
$new_input[\'eswc_redirect\'] = ( $input[\'eswc_redirect\'] == 1 ? 1 : 0 );
return $new_input;
}
/**
* Get the settings option array and print one of its values
*/
public function eswc_kill_gutenberg_cb() {
printf(
\'<fieldset>
<label><input id="eswc_kill_gutenberg" type="checkbox" name="eswc_settingz[eswc_kill_gutenberg]" value="1" %1$s />%2$s</label>
</fieldset>\',
isset( $this->options[\'eswc_kill_gutenberg\'] ) && ( 1 == $this->options[\'eswc_kill_gutenberg\'] ) ? \'checked="checked" \':\'\',
__( \'Disable Gutenberg editor. Don\\\'t load Gutenberg-related stylesheets from WordPress core, WooCommerce and Storefront.\', \'extra-settings-for-woocommerce\' )
);
}
public function eswc_change_email_author_cb() {
printf(
\'<fieldset>
<label><input id="eswc_change_email_author" type="checkbox" name="eswc_settingz[eswc_change_email_author]" value="1" %1$s />%2$s</label>
</fieldset>\',
isset( $this->options[\'eswc_change_email_author\'] ) && ( 1 == $this->options[\'eswc_change_email_author\'] ) ? \'checked="checked" \':\'\',
__( \'Default is WordPress, wordpress@yourdomain.com. Change to: "Site Title" from Settings > General, custom email entered below.\', \'extra-settings-for-woocommerce\' )
);
}
public function eswc_redirect_cb() {
printf(
\'<fieldset>
<label><input id="eswc_redirect" type="checkbox" name="eswc_settingz[eswc_redirect]" value="1" %1$s />%2$s</label>
</fieldset>
<p class="description">%3$s</p>\',
isset( $this->options[\'eswc_redirect\'] ) && ( 1 == $this->options[\'eswc_redirect\'] ) ? \'checked="checked" \':\'\',
__( \'After a successful login, redirect customers to previously visited page and users with admin access to dashboard.\', \'extra-settings-for-woocommerce\' ),
__( \'By default WooCommerce redirects to "My account" page. Customer roles: customer, subscriber. Admin access roles: administrator, shop_manager, editor, author, contributor.\', \'extra-settings-for-woocommerce\' )
);
}
}
$eswc_settingz_page = new extra_settings_settings();
最合适的回答,由SO网友:Sally CJ 整理而成
首先,只有选择了正确的选项卡,才能注册字段,以避免在保存时将其他选项卡中的值重置为默认值。
因此,您应该向wp-admin/options.php
表单提交到的页面。
您只需将其作为查询字符串传递到表单中action
属性值:
<form method="post" action="<?php echo esc_url( add_query_arg( // wrapped for clarity
\'tab\', $active_tab, admin_url( \'options.php\' )
) ); ?>">
或
create_settings_page()
, 添加一个隐藏的输入字段,该字段的值为tab slug:
echo \'<input type="hidden" name="tab" value="\' . esc_attr( $active_tab ) . \'" />\';
submit_button();
然后在
display_options()
, 使用检索选项卡段塞
$_REQUEST
:
$active_tab = isset( $_REQUEST[\'tab\'] ) ? $_REQUEST[\'tab\'] : \'general\';
无论哪种方式,关键是
register_setting()
中的调用
display_options()
被调用。否则,WordPress会抛出“找不到选项页”错误,因为选项页未注册。
您可以使用whitelist_options
过滤器,但我更希望register_setting()
调用,所以我删除了这个和相关的回调(whitelist_custom_options_page()
):
add_action( \'whitelist_options\', array( $this, \'whitelist_custom_options_page\' ),11 );
第二件事,因为您使用的是相同的数据库选项名称(
eswc_settingz
) 对于所有选项卡/字段,应将保存的数据与提交的数据合并:
public function sanitize_general( $input ) {
$new_input = (array) get_option( \'eswc_settingz\' ); // get saved data
... add/update new data
return $new_input;
}
public function sanitize_account( $input ) {
$new_input = (array) get_option( \'eswc_settingz\' ); // get saved data
... add/update new data
return $new_input;
}
或者可以使用不同的数据库选项名称:
register_setting( \'general_section\', \'eswc_general_settingz\', array( $this, \'sanitize_general\' ) );
register_setting( \'account_section\', \'eswc_account_settingz\', array( $this, \'sanitize_account\' ) );
顺便问一下,是不是
settingz
打字错误?也许是命中注定的
settings
?...