WordPress 插件设置未保存并在提交时被重定向到 /wp-admin/options.php(生成 404)
WordPress plugin settings not saving and getting redirected to /wp-admin/options.php (which generates a 404) on submit
我正在使用 https://github.com/nadeem-khan/WordPress-Plugin-Template 作为入门模板创建 WordPress。
这是我的设置 class 文件,名为 'class-xyz.php':
<?php
if (!defined('ABSPATH'))
exit;
class Xyz_Settings {
/**
* The single instance of Xyz_Settings.
* @var object
* @access private
* @since 1.0.0
*/
private static $_instance = null;
/**
* The main plugin object.
* @var object
* @access public
* @since 1.0.0
*/
public $parent = null;
/**
* Prefix for plugin settings.
* @var string
* @access public
* @since 1.0.0
*/
public $base = '';
/**
* Available settings for plugin.
* @var array
* @access public
* @since 1.0.0
*/
public $settings = array();
public function __construct($parent) {
$this->parent = $parent;
$this->base = 'xyzsms_';
// Initialise settings
add_action('admin_init', array($this, 'init_settings'));
// Register plugin settings
add_action('admin_init', array($this, 'register_settings'));
// Add settings page to menu
add_action('admin_menu', array($this, 'add_menu_item'));
// Add settings link to plugins page
add_filter('plugin_action_links_' . plugin_basename($this->parent->file), array($this, 'add_settings_link'));
}
/**
* Initialise settings
* @return void
*/
public function init_settings() {
$this->settings = $this->settings_fields();
}
/**
* Add settings page to admin menu
* @return void
*/
public function add_menu_item() {
$page = add_options_page(__('XYZ Settings', 'xyz-template'), __('XYZ Settings', 'xyz-template'), 'manage_options', 'xyz_template_settings', array($this, 'settings_page'));
add_action('admin_print_styles-' . $page, array($this, 'settings_assets'));
}
/**
* Load settings JS & CSS
* @return void
*/
public function settings_assets() {
// We're including the farbtastic script & styles here because they're needed for the colour picker
// If you're not including a colour picker field then you can leave these calls out as well as the farbtastic dependency for the wpt-admin-js script below
wp_enqueue_style('farbtastic');
wp_enqueue_script('farbtastic');
// We're including the WP media scripts here because they're needed for the image upload field
// If you're not including an image upload then you can leave this function call out
wp_enqueue_media();
wp_register_script($this->parent->_token . '-settings-js', $this->parent->assets_url . 'js/settings' . $this->parent->script_suffix . '.js', array('farbtastic', 'jquery'), '1.0.0');
wp_enqueue_script($this->parent->_token . '-settings-js');
}
/**
* Add settings link to plugin list table
* @param array $links Existing links
* @return array Modified links
*/
public function add_settings_link($links) {
$settings_link = '<a href="options-general.php?page=xyz_template_settings">' . __('Settings', 'xyz-template') . '</a>';
array_push($links, $settings_link);
return $links;
}
/**
* Build settings fields
* @return array Fields to be displayed on settings page
*/
private function settings_fields() {
$settings['social-bar-position'] = array(
'title' => __('Bar Position', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_position',
'label' => __('Position', 'xyz-plugin-bar'),
'description' => __('Select the position', 'xyz-plugin-bar'),
'type' => 'radio',
'options' => array('left' => 'Left', 'right' => 'Right'),
'default' => 'left'
),
array(
'id' => 'xyz_margin_top',
'label' => __('Bar Margin Top', 'xyz-plugin-bar'),
'description' => __('Define the margin top', 'xyz-plugin-bar'),
'type' => 'text',
'placeholder' => __('Enter margin.', 'xyz-plugin-bar'),
'default' => '200px'
)
)
);
$settings['social-networks-bar'] = array(
'title' => __('Social Networks', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_networks',
'label' => __('Social', 'xyz-plugin-bar'),
'description' => __('Select social.', 'xyz-plugin-bar'),
'type' => 'checkbox_multi',
'options' => array(
'facebook' => 'Facebook'
)
)
)
);
$settings['links-bar'] = array(
'title' => __('Links', 'xyz-plugin-bar'),
'description' => __('Enter the Urls for all the selected social networks:', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'facebook_url',
'label' => __('Facebook URL', 'xyz-plugin-bar'),
'description' => __('Enter the URL for Facebook.', 'xyz-plugin-bar'),
'type' => 'text',
'placeholder' => __('Enter Facebook URL', 'xyz-plugin-bar'),
'default' => ''
)
)
);
$settings['custom-classes-bar'] = array(
'title' => __('Custom Classes', 'xyz-plugin-bar'),
'description' => __('Add custom classes in the main parent container of the bar (will affect shortcodes as well):', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_custom_class',
'label' => __('Add Custom Classes in the Bar Parent Container'),
'description' => __('Add your own custom CSS class (like customclass1 customclass2). Leave empty if default styling is desired.', 'xyz-plugin-bar'),
'type' => 'textarea',
'default' => '',
'placeholder' => __('Add custom classes like .custom_class1 .custom_class2 .custom_class3 to the main container of the social bar.', 'xyz-plugin-bar')
)
)
);
$settings['social-bar-custom-colors'] = array(
'title' => __('Bar Icons Colors', 'xyz-plugin-bar'),
'description' => __('Select the colors', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'bar_facebook_icon_custom_color',
'label' => __('Facebook Icon Color', 'xyz-plugin-bar'),
'description' => __('Default color: #FEFEFE ', 'xyz-plugin-bar'),
'type' => 'color',
'default' => '#FEFEFE'
)
)
);
$settings['add-custom-css-bar'] = array(
'title' => __('Add CSS', 'xyz-plugin-bar'),
'label' => __('Add CSS', 'xyz-plugin-bar'),
'description' => __('Paste your CSS', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_add_custom_css',
'label' => __('Custom CSS', 'wordpress'),
'description' => __('Do not style', 'xyz-plugin-bar'),
'type' => 'textarea',
'default' => '',
'placeholder' => __('Do not style .', 'xyz-plugin-bar')
)
)
);
$settings = apply_filters('xyz_fields', $settings);
return $settings;
}
/**
* Register plugin settings
* @return void
*/
public function register_settings() {
if (is_array($this->settings)) {
foreach ($this->settings as $section => $data) {
// Add section to page
add_settings_section($section, $data['title'], array($this, 'settings_section'), 'xyz_template_settings');
foreach ($data['fields'] as $field) {
// Validation callback for field
$validation = '';
if (isset($field['callback'])) {
$validation = $field['callback'];
}
// Register field
$option_name = $this->base . $field['id'];
register_setting('xyz_template_settings', $option_name, $validation);
// Add field to page
add_settings_field($field['id'], $field['label'], array($this, 'display_field'), 'xyz_template_settings', $section, array('field' => $field));
}
}
}
}
public function settings_section($section) {
$html = '<p> ' . $this->settings[$section['id']]['description'] . '</p>' . "\n";
echo $html;
}
/**
* Generate HTML for displaying fields
* @param array $args Field data
* @return void
*/
public function display_field($args) {
$field = $args['field'];
$html = '';
$option_name = $this->base . $field['id'];
$option = get_option($option_name);
$data = '';
if (isset($field['default'])) {
$data = $field['default'];
if ($option) {
$data = $option;
}
}
switch ($field['type']) {
case 'text':
case 'password':
case 'number':
$html .= '<input id="' . esc_attr($field['id']) . '" type="' . $field['type'] . '" name="' . esc_attr($option_name) . '" placeholder="' . esc_attr($field['placeholder']) . '" value="' . $data . '"/>' . "\n";
break;
case 'text_secret':
$html .= '<input id="' . esc_attr($field['id']) . '" type="text" name="' . esc_attr($option_name) . '" placeholder="' . esc_attr($field['placeholder']) . '" value=""/>' . "\n";
break;
case 'textarea':
$html .= '<textarea id="' . esc_attr($field['id']) . '" rows="5" cols="50" name="' . esc_attr($option_name) . '" placeholder="' . esc_attr($field['placeholder']) . '">' . $data . '</textarea><br/>' . "\n";
break;
case 'checkbox':
$checked = '';
if ($option && 'on' == $option) {
$checked = 'checked="checked"';
}
$html .= '<input id="' . esc_attr($field['id']) . '" type="' . $field['type'] . '" name="' . esc_attr($option_name) . '" ' . $checked . '/>' . "\n";
break;
case 'checkbox_multi':
foreach ($field['options'] as $k => $v) {
$checked = false;
if (in_array($k, $data)) {
$checked = true;
}
$html .= '<label for="' . esc_attr($field['id'] . '_' . $k) . '"><input type="checkbox" ' . checked($checked, true, false) . ' name="' . esc_attr($option_name) . '[]" value="' . esc_attr($k) . '" id="' . esc_attr($field['id'] . '_' . $k) . '" /> ' . $v . '</label> ';
}
break;
case 'radio':
foreach ($field['options'] as $k => $v) {
$checked = false;
if ($k == $data) {
$checked = true;
}
$html .= '<label for="' . esc_attr($field['id'] . '_' . $k) . '"><input type="radio" ' . checked($checked, true, false) . ' name="' . esc_attr($option_name) . '" value="' . esc_attr($k) . '" id="' . esc_attr($field['id'] . '_' . $k) . '" /> ' . $v . '</label> ';
}
break;
case 'select':
$html .= '<select name="' . esc_attr($option_name) . '" id="' . esc_attr($field['id']) . '">';
foreach ($field['options'] as $k => $v) {
$selected = false;
if ($k == $data) {
$selected = true;
}
$html .= '<option ' . selected($selected, true, false) . ' value="' . esc_attr($k) . '">' . $v . '</option>';
}
$html .= '</select> ';
break;
case 'select_multi':
$html .= '<select name="' . esc_attr($option_name) . '[]" id="' . esc_attr($field['id']) . '" multiple="multiple">';
foreach ($field['options'] as $k => $v) {
$selected = false;
if (in_array($k, $data)) {
$selected = true;
}
$html .= '<option ' . selected($selected, true, false) . ' value="' . esc_attr($k) . '" />' . $v . '</label> ';
}
$html .= '</select> ';
break;
case 'image':
$image_thumb = '';
if ($data) {
$image_thumb = wp_get_attachment_thumb_url($data);
}
$html .= '<img id="' . $option_name . '_preview" class="image_preview" src="' . $image_thumb . '" /><br/>' . "\n";
$html .= '<input id="' . $option_name . '_button" type="button" data-uploader_title="' . __('Upload an image', 'xyz-template') . '" data-uploader_button_text="' . __('Use image', 'xyz-template') . '" class="image_upload_button button" value="' . __('Upload new image', 'xyz-template') . '" />' . "\n";
$html .= '<input id="' . $option_name . '_delete" type="button" class="image_delete_button button" value="' . __('Remove image', 'xyz-template') . '" />' . "\n";
$html .= '<input id="' . $option_name . '" class="image_data_field" type="hidden" name="' . $option_name . '" value="' . $data . '"/><br/>' . "\n";
break;
case 'color':
?><div class="color-picker" style="position:relative;">
<input type="text" name="<?php esc_attr_e($option_name); ?>" class="color" value="<?php esc_attr_e($data); ?>" />
<div style="position:absolute;background:#FFF;z-index:99;border-radius:100%;" class="colorpicker"></div>
</div>
<?php
break;
}
switch ($field['type']) {
case 'checkbox_multi':
case 'radio':
case 'select_multi':
$html .= '<br/><span class="description">' . $field['description'] . '</span>';
break;
default:
$html .= '<label for="' . esc_attr($field['id']) . '"><span class="description">' . $field['description'] . '</span></label>' . "\n";
break;
}
echo $html;
}
/**
* Validate individual settings field
* @param string $data Inputted value
* @return string Validated value
*/
public function validate_field($data) {
if ($data && strlen($data) > 0 && $data != '') {
$data = urlencode(strtolower(str_replace(' ', '-', $data)));
}
return $data;
}
/**
* Load settings page content
* @return void
*/
public function settings_page() {
// Build page HTML
$html = '<div class="wrap" id="xyz_settings">' . "\n";
$html .= '<h2>' . __('XYZ Settings', 'xyz-template') . '</h2>' . "\n";
$html .= '<form method="post" action="options.php" enctype="multipart/form-data">' . "\n";
// Setup navigation
$html .= '<ul id="settings-sections" class="subsubsub hide-if-no-js">' . "\n";
$html .= '<li><a class="tab all current" href="#all">' . __('All', 'xyz-template') . '</a></li>' . "\n";
foreach ($this->settings as $section => $data) {
$html .= '<li>| <a class="tab" href="#' . $section . '">' . $data['title'] . '</a></li>' . "\n";
}
$html .= '</ul>' . "\n";
$html .= '<div class="clear"></div>' . "\n";
// Get settings fields
ob_start();
settings_fields('xyz_template_settings');
do_settings_sections('xyz_template_settings');
$html .= ob_get_clean();
$html .= '<p class="submit">' . "\n";
$html .= '<input name="Submit" type="submit" class="button-primary" value="' . esc_attr(__('Save Settings', 'xyz-template')) . '" />' . "\n";
$html .= '</p>' . "\n";
$html .= '</form>' . "\n";
$html .= '</div>' . "\n";
echo $html;
}
/**
* Main Xyz_Settings Instance
*
* Ensures only one instance of Xyz_Settings is loaded or can be loaded.
*
* @since 1.0.0
* @static
* @see Xyz()
* @return Main Xyz_Settings instance
*/
public static function instance($parent) {
if (is_null(self::$_instance)) {
self::$_instance = new self($parent);
}
return self::$_instance;
}
// End instance()
/**
* Cloning is forbidden.
*
* @since 1.0.0
*/
public function __clone() {
_doing_it_wrong(__FUNCTION__, __('Cheatin’ huh?'), $this->parent->_version);
}
// End __clone()
/**
* Unserializing instances of this class is forbidden.
*
* @since 1.0.0
*/
public function __wakeup() {
_doing_it_wrong(__FUNCTION__, __('Cheatin’ huh?'), $this->parent->_version);
}
// End __wakeup()
}
所有设置字段都正确显示,但是一旦按下提交按钮,就会生成 404,并且不会保存任何设置。我在这里错过了什么?
更新: 下面是在另一个文件中初始化 Xyz_Settings class 的方式:
function Xyz_bar_init () {
$instance = Xyz_bar::instance( __FILE__, '1.0.0' );
if( is_null( $instance->settings ) ) {
$instance->settings = Xyz_Settings::instance( $instance );
}
return $instance;
}
Xyz_bar_init();
UPDATE(2): 我已经激活了我自己的插件的一个非常精简的版本,只有 2-3 个设置选项,它似乎工作得很好(因为值越来越saved/retrieved 在数据库中正确)。设置选项的剪切数量是否会导致具有 200 多个选项的完整插件出现问题(请注意,我使用的是资源有限的共享主机)?
我已经对此文件进行了更改,现在 post 显示:- class-wordpress-plugin-template-post_type.php
你的代码:-
// Post type name and labels
$this->post_type = 'post_type';
$this->plural = _x( 'Posts', 'post type general name' , 'wordpress-plugin-template' );
$this->single = _x( 'Post', 'post type singular name' , 'wordpress-plugin-template' );
我的代码:-
// Post type name and labels
$this->post_type = 'post_type1'; // change your value here
$this->plural = _x( 'Your Posts', 'post type general name' , 'wordpress-plugin-template' );
$this->single = _x( 'Post', 'post type singular name' , 'wordpress-plugin-template' );
转到 admin/permalinks 并再次保存您的设置,无需更改任何内容。十分之九这将在添加自定义设置后解决 404 问题(自定义模板也是如此)。
您也可以在构造函数的末尾添加“flush_rewrite_rules();
”来避免这一步。
[编辑]
好吧,既然这样...您的表单操作仅指向 "options.php"。这意味着您的插件将在插件或根文件夹中查找 options.php。应该是 site_url()."/wp-admin/options.php"
.
如果要保存大量选项,请确保不要使 max_input_vars
限制饱和,该限制在 PHP 5.3.9 中引入以限制可接受的输入变量的数量- 来自 PHP 文档:
How many input variables may be accepted (limit is applied to $_GET,
$_POST and $_COOKIE superglobal separately). Use of this directive
mitigates the possibility of denial of service attacks which use hash
collisions.
您应该可以在 php.ini
中根据需要修改此值。
另外记得检查你的错误日志。
我正在使用 https://github.com/nadeem-khan/WordPress-Plugin-Template 作为入门模板创建 WordPress。
这是我的设置 class 文件,名为 'class-xyz.php':
<?php
if (!defined('ABSPATH'))
exit;
class Xyz_Settings {
/**
* The single instance of Xyz_Settings.
* @var object
* @access private
* @since 1.0.0
*/
private static $_instance = null;
/**
* The main plugin object.
* @var object
* @access public
* @since 1.0.0
*/
public $parent = null;
/**
* Prefix for plugin settings.
* @var string
* @access public
* @since 1.0.0
*/
public $base = '';
/**
* Available settings for plugin.
* @var array
* @access public
* @since 1.0.0
*/
public $settings = array();
public function __construct($parent) {
$this->parent = $parent;
$this->base = 'xyzsms_';
// Initialise settings
add_action('admin_init', array($this, 'init_settings'));
// Register plugin settings
add_action('admin_init', array($this, 'register_settings'));
// Add settings page to menu
add_action('admin_menu', array($this, 'add_menu_item'));
// Add settings link to plugins page
add_filter('plugin_action_links_' . plugin_basename($this->parent->file), array($this, 'add_settings_link'));
}
/**
* Initialise settings
* @return void
*/
public function init_settings() {
$this->settings = $this->settings_fields();
}
/**
* Add settings page to admin menu
* @return void
*/
public function add_menu_item() {
$page = add_options_page(__('XYZ Settings', 'xyz-template'), __('XYZ Settings', 'xyz-template'), 'manage_options', 'xyz_template_settings', array($this, 'settings_page'));
add_action('admin_print_styles-' . $page, array($this, 'settings_assets'));
}
/**
* Load settings JS & CSS
* @return void
*/
public function settings_assets() {
// We're including the farbtastic script & styles here because they're needed for the colour picker
// If you're not including a colour picker field then you can leave these calls out as well as the farbtastic dependency for the wpt-admin-js script below
wp_enqueue_style('farbtastic');
wp_enqueue_script('farbtastic');
// We're including the WP media scripts here because they're needed for the image upload field
// If you're not including an image upload then you can leave this function call out
wp_enqueue_media();
wp_register_script($this->parent->_token . '-settings-js', $this->parent->assets_url . 'js/settings' . $this->parent->script_suffix . '.js', array('farbtastic', 'jquery'), '1.0.0');
wp_enqueue_script($this->parent->_token . '-settings-js');
}
/**
* Add settings link to plugin list table
* @param array $links Existing links
* @return array Modified links
*/
public function add_settings_link($links) {
$settings_link = '<a href="options-general.php?page=xyz_template_settings">' . __('Settings', 'xyz-template') . '</a>';
array_push($links, $settings_link);
return $links;
}
/**
* Build settings fields
* @return array Fields to be displayed on settings page
*/
private function settings_fields() {
$settings['social-bar-position'] = array(
'title' => __('Bar Position', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_position',
'label' => __('Position', 'xyz-plugin-bar'),
'description' => __('Select the position', 'xyz-plugin-bar'),
'type' => 'radio',
'options' => array('left' => 'Left', 'right' => 'Right'),
'default' => 'left'
),
array(
'id' => 'xyz_margin_top',
'label' => __('Bar Margin Top', 'xyz-plugin-bar'),
'description' => __('Define the margin top', 'xyz-plugin-bar'),
'type' => 'text',
'placeholder' => __('Enter margin.', 'xyz-plugin-bar'),
'default' => '200px'
)
)
);
$settings['social-networks-bar'] = array(
'title' => __('Social Networks', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_networks',
'label' => __('Social', 'xyz-plugin-bar'),
'description' => __('Select social.', 'xyz-plugin-bar'),
'type' => 'checkbox_multi',
'options' => array(
'facebook' => 'Facebook'
)
)
)
);
$settings['links-bar'] = array(
'title' => __('Links', 'xyz-plugin-bar'),
'description' => __('Enter the Urls for all the selected social networks:', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'facebook_url',
'label' => __('Facebook URL', 'xyz-plugin-bar'),
'description' => __('Enter the URL for Facebook.', 'xyz-plugin-bar'),
'type' => 'text',
'placeholder' => __('Enter Facebook URL', 'xyz-plugin-bar'),
'default' => ''
)
)
);
$settings['custom-classes-bar'] = array(
'title' => __('Custom Classes', 'xyz-plugin-bar'),
'description' => __('Add custom classes in the main parent container of the bar (will affect shortcodes as well):', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_custom_class',
'label' => __('Add Custom Classes in the Bar Parent Container'),
'description' => __('Add your own custom CSS class (like customclass1 customclass2). Leave empty if default styling is desired.', 'xyz-plugin-bar'),
'type' => 'textarea',
'default' => '',
'placeholder' => __('Add custom classes like .custom_class1 .custom_class2 .custom_class3 to the main container of the social bar.', 'xyz-plugin-bar')
)
)
);
$settings['social-bar-custom-colors'] = array(
'title' => __('Bar Icons Colors', 'xyz-plugin-bar'),
'description' => __('Select the colors', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'bar_facebook_icon_custom_color',
'label' => __('Facebook Icon Color', 'xyz-plugin-bar'),
'description' => __('Default color: #FEFEFE ', 'xyz-plugin-bar'),
'type' => 'color',
'default' => '#FEFEFE'
)
)
);
$settings['add-custom-css-bar'] = array(
'title' => __('Add CSS', 'xyz-plugin-bar'),
'label' => __('Add CSS', 'xyz-plugin-bar'),
'description' => __('Paste your CSS', 'xyz-plugin-bar'),
'fields' => array(
array(
'id' => 'xyz_add_custom_css',
'label' => __('Custom CSS', 'wordpress'),
'description' => __('Do not style', 'xyz-plugin-bar'),
'type' => 'textarea',
'default' => '',
'placeholder' => __('Do not style .', 'xyz-plugin-bar')
)
)
);
$settings = apply_filters('xyz_fields', $settings);
return $settings;
}
/**
* Register plugin settings
* @return void
*/
public function register_settings() {
if (is_array($this->settings)) {
foreach ($this->settings as $section => $data) {
// Add section to page
add_settings_section($section, $data['title'], array($this, 'settings_section'), 'xyz_template_settings');
foreach ($data['fields'] as $field) {
// Validation callback for field
$validation = '';
if (isset($field['callback'])) {
$validation = $field['callback'];
}
// Register field
$option_name = $this->base . $field['id'];
register_setting('xyz_template_settings', $option_name, $validation);
// Add field to page
add_settings_field($field['id'], $field['label'], array($this, 'display_field'), 'xyz_template_settings', $section, array('field' => $field));
}
}
}
}
public function settings_section($section) {
$html = '<p> ' . $this->settings[$section['id']]['description'] . '</p>' . "\n";
echo $html;
}
/**
* Generate HTML for displaying fields
* @param array $args Field data
* @return void
*/
public function display_field($args) {
$field = $args['field'];
$html = '';
$option_name = $this->base . $field['id'];
$option = get_option($option_name);
$data = '';
if (isset($field['default'])) {
$data = $field['default'];
if ($option) {
$data = $option;
}
}
switch ($field['type']) {
case 'text':
case 'password':
case 'number':
$html .= '<input id="' . esc_attr($field['id']) . '" type="' . $field['type'] . '" name="' . esc_attr($option_name) . '" placeholder="' . esc_attr($field['placeholder']) . '" value="' . $data . '"/>' . "\n";
break;
case 'text_secret':
$html .= '<input id="' . esc_attr($field['id']) . '" type="text" name="' . esc_attr($option_name) . '" placeholder="' . esc_attr($field['placeholder']) . '" value=""/>' . "\n";
break;
case 'textarea':
$html .= '<textarea id="' . esc_attr($field['id']) . '" rows="5" cols="50" name="' . esc_attr($option_name) . '" placeholder="' . esc_attr($field['placeholder']) . '">' . $data . '</textarea><br/>' . "\n";
break;
case 'checkbox':
$checked = '';
if ($option && 'on' == $option) {
$checked = 'checked="checked"';
}
$html .= '<input id="' . esc_attr($field['id']) . '" type="' . $field['type'] . '" name="' . esc_attr($option_name) . '" ' . $checked . '/>' . "\n";
break;
case 'checkbox_multi':
foreach ($field['options'] as $k => $v) {
$checked = false;
if (in_array($k, $data)) {
$checked = true;
}
$html .= '<label for="' . esc_attr($field['id'] . '_' . $k) . '"><input type="checkbox" ' . checked($checked, true, false) . ' name="' . esc_attr($option_name) . '[]" value="' . esc_attr($k) . '" id="' . esc_attr($field['id'] . '_' . $k) . '" /> ' . $v . '</label> ';
}
break;
case 'radio':
foreach ($field['options'] as $k => $v) {
$checked = false;
if ($k == $data) {
$checked = true;
}
$html .= '<label for="' . esc_attr($field['id'] . '_' . $k) . '"><input type="radio" ' . checked($checked, true, false) . ' name="' . esc_attr($option_name) . '" value="' . esc_attr($k) . '" id="' . esc_attr($field['id'] . '_' . $k) . '" /> ' . $v . '</label> ';
}
break;
case 'select':
$html .= '<select name="' . esc_attr($option_name) . '" id="' . esc_attr($field['id']) . '">';
foreach ($field['options'] as $k => $v) {
$selected = false;
if ($k == $data) {
$selected = true;
}
$html .= '<option ' . selected($selected, true, false) . ' value="' . esc_attr($k) . '">' . $v . '</option>';
}
$html .= '</select> ';
break;
case 'select_multi':
$html .= '<select name="' . esc_attr($option_name) . '[]" id="' . esc_attr($field['id']) . '" multiple="multiple">';
foreach ($field['options'] as $k => $v) {
$selected = false;
if (in_array($k, $data)) {
$selected = true;
}
$html .= '<option ' . selected($selected, true, false) . ' value="' . esc_attr($k) . '" />' . $v . '</label> ';
}
$html .= '</select> ';
break;
case 'image':
$image_thumb = '';
if ($data) {
$image_thumb = wp_get_attachment_thumb_url($data);
}
$html .= '<img id="' . $option_name . '_preview" class="image_preview" src="' . $image_thumb . '" /><br/>' . "\n";
$html .= '<input id="' . $option_name . '_button" type="button" data-uploader_title="' . __('Upload an image', 'xyz-template') . '" data-uploader_button_text="' . __('Use image', 'xyz-template') . '" class="image_upload_button button" value="' . __('Upload new image', 'xyz-template') . '" />' . "\n";
$html .= '<input id="' . $option_name . '_delete" type="button" class="image_delete_button button" value="' . __('Remove image', 'xyz-template') . '" />' . "\n";
$html .= '<input id="' . $option_name . '" class="image_data_field" type="hidden" name="' . $option_name . '" value="' . $data . '"/><br/>' . "\n";
break;
case 'color':
?><div class="color-picker" style="position:relative;">
<input type="text" name="<?php esc_attr_e($option_name); ?>" class="color" value="<?php esc_attr_e($data); ?>" />
<div style="position:absolute;background:#FFF;z-index:99;border-radius:100%;" class="colorpicker"></div>
</div>
<?php
break;
}
switch ($field['type']) {
case 'checkbox_multi':
case 'radio':
case 'select_multi':
$html .= '<br/><span class="description">' . $field['description'] . '</span>';
break;
default:
$html .= '<label for="' . esc_attr($field['id']) . '"><span class="description">' . $field['description'] . '</span></label>' . "\n";
break;
}
echo $html;
}
/**
* Validate individual settings field
* @param string $data Inputted value
* @return string Validated value
*/
public function validate_field($data) {
if ($data && strlen($data) > 0 && $data != '') {
$data = urlencode(strtolower(str_replace(' ', '-', $data)));
}
return $data;
}
/**
* Load settings page content
* @return void
*/
public function settings_page() {
// Build page HTML
$html = '<div class="wrap" id="xyz_settings">' . "\n";
$html .= '<h2>' . __('XYZ Settings', 'xyz-template') . '</h2>' . "\n";
$html .= '<form method="post" action="options.php" enctype="multipart/form-data">' . "\n";
// Setup navigation
$html .= '<ul id="settings-sections" class="subsubsub hide-if-no-js">' . "\n";
$html .= '<li><a class="tab all current" href="#all">' . __('All', 'xyz-template') . '</a></li>' . "\n";
foreach ($this->settings as $section => $data) {
$html .= '<li>| <a class="tab" href="#' . $section . '">' . $data['title'] . '</a></li>' . "\n";
}
$html .= '</ul>' . "\n";
$html .= '<div class="clear"></div>' . "\n";
// Get settings fields
ob_start();
settings_fields('xyz_template_settings');
do_settings_sections('xyz_template_settings');
$html .= ob_get_clean();
$html .= '<p class="submit">' . "\n";
$html .= '<input name="Submit" type="submit" class="button-primary" value="' . esc_attr(__('Save Settings', 'xyz-template')) . '" />' . "\n";
$html .= '</p>' . "\n";
$html .= '</form>' . "\n";
$html .= '</div>' . "\n";
echo $html;
}
/**
* Main Xyz_Settings Instance
*
* Ensures only one instance of Xyz_Settings is loaded or can be loaded.
*
* @since 1.0.0
* @static
* @see Xyz()
* @return Main Xyz_Settings instance
*/
public static function instance($parent) {
if (is_null(self::$_instance)) {
self::$_instance = new self($parent);
}
return self::$_instance;
}
// End instance()
/**
* Cloning is forbidden.
*
* @since 1.0.0
*/
public function __clone() {
_doing_it_wrong(__FUNCTION__, __('Cheatin’ huh?'), $this->parent->_version);
}
// End __clone()
/**
* Unserializing instances of this class is forbidden.
*
* @since 1.0.0
*/
public function __wakeup() {
_doing_it_wrong(__FUNCTION__, __('Cheatin’ huh?'), $this->parent->_version);
}
// End __wakeup()
}
所有设置字段都正确显示,但是一旦按下提交按钮,就会生成 404,并且不会保存任何设置。我在这里错过了什么?
更新: 下面是在另一个文件中初始化 Xyz_Settings class 的方式:
function Xyz_bar_init () {
$instance = Xyz_bar::instance( __FILE__, '1.0.0' );
if( is_null( $instance->settings ) ) {
$instance->settings = Xyz_Settings::instance( $instance );
}
return $instance;
}
Xyz_bar_init();
UPDATE(2): 我已经激活了我自己的插件的一个非常精简的版本,只有 2-3 个设置选项,它似乎工作得很好(因为值越来越saved/retrieved 在数据库中正确)。设置选项的剪切数量是否会导致具有 200 多个选项的完整插件出现问题(请注意,我使用的是资源有限的共享主机)?
我已经对此文件进行了更改,现在 post 显示:- class-wordpress-plugin-template-post_type.php 你的代码:-
// Post type name and labels
$this->post_type = 'post_type';
$this->plural = _x( 'Posts', 'post type general name' , 'wordpress-plugin-template' );
$this->single = _x( 'Post', 'post type singular name' , 'wordpress-plugin-template' );
我的代码:-
// Post type name and labels
$this->post_type = 'post_type1'; // change your value here
$this->plural = _x( 'Your Posts', 'post type general name' , 'wordpress-plugin-template' );
$this->single = _x( 'Post', 'post type singular name' , 'wordpress-plugin-template' );
转到 admin/permalinks 并再次保存您的设置,无需更改任何内容。十分之九这将在添加自定义设置后解决 404 问题(自定义模板也是如此)。
您也可以在构造函数的末尾添加“flush_rewrite_rules();
”来避免这一步。
[编辑]
好吧,既然这样...您的表单操作仅指向 "options.php"。这意味着您的插件将在插件或根文件夹中查找 options.php。应该是 site_url()."/wp-admin/options.php"
.
如果要保存大量选项,请确保不要使 max_input_vars
限制饱和,该限制在 PHP 5.3.9 中引入以限制可接受的输入变量的数量- 来自 PHP 文档:
How many input variables may be accepted (limit is applied to $_GET, $_POST and $_COOKIE superglobal separately). Use of this directive mitigates the possibility of denial of service attacks which use hash collisions.
您应该可以在 php.ini
中根据需要修改此值。
另外记得检查你的错误日志。