I created theme options page using Settings API, everything works fine but I can’t save options. I tried to figure it out where I missed something but I failed. Any idea what can cause this problem?
Here’s code of my options page
<?php
/**
* This functions registers default options values for Evolutionary theme
* settings
*/
function ev_theme_settings_defaults() {
$options = array(
'color_scheme' => 'blue',
'copyright' => '',
'nav_hide_home' => false,
'nav_hide_sec' => false,
'nav_show_lvl' => false,
'featured_show' => false,
'featured_pause' => false,
'featured_speed' => 5,
'ad1_link' => '',
'ad1_image' => '',
'ad2_link' => '',
'ad2_image' => '',
'ad3_link' => '',
'ad3_image' => '',
'ad4_link' => '',
'ad4_image' => ''
);
return $options;
// Change to apply_filters( 'ev_theme_settings_defaults', $options );
}
/**
* Create helper function for theme colors
*/
function ev_get_valid_color_schemes(){
$color_schemes = array(
'blue' => __( 'Blue', 'evolutionary' ),
'green' => __( 'Green', 'evolutionary' ),
'red' => __( 'Red', 'evolutionary' ),
'black' => __( 'Black', 'evolutionary')
);
return $color_schemes;
}
/**
* Setup initial theme options
*/
function ev_options_init() {
// Set options equal to defaults
global $ev_options;
$ev_options = ev_theme_settings_defaults();
if ( false === $ev_options ) {
$ev_options = ev_theme_settings_defaults();
}
update_option( 'theme_evolutionary_options', $ev_options );
}
add_action( 'after_setup_theme', 'ev_options_init', 9 );
/**
* Add theme options page to admin menu
*/
function ev_menu_options() {
add_theme_page( __( 'Theme Options', 'evolutionary' ), __( 'Theme Options', 'evolutionary' ), 'edit_theme_options', 'evolutionary-settings', 'ev_admin_options_page' );
}
add_action( 'admin_menu', 'ev_menu_options' );
/**
* Register theme options
*/
function ev_register_options() {
register_setting( 'theme_evolutionary_options', 'theme_evolutionary_options', 'ev_options_validate' );
/**
* Defining settings sections and fields
* fist setting creates sections for general options
*/
add_settings_section( 'ev_settings_general_options', __( 'General Options', 'evolutionary' ), 'ev_settings_general_options', 'evolutionary' );
// Creates section for navigation options
add_settings_section( 'ev_settings_nav_options', __( 'Navigation', 'evolutionary' ), 'ev_settings_nav_options', 'evolutionary' );
// Section for featured post options
add_settings_section( 'ev_settings_featured_options', __( 'Featured Posts', 'evolutionary' ), 'ev_settings_featured_options', 'evolutionary' );
// Section for Advertising options
add_settings_section( 'ev_settings_ad_options', __( 'Advertising', 'evolutionary' ), 'ev_settings_ad_options', 'evolutionary' );
/**
* Created empty callbacks for setions
*/
function ev_settings_general_options() {
// Put callback code here
}
function ev_settings_nav_options() {
// callback
}
function ev_settings_featured_options() {
// callback
}
function ev_settings_ad_options() {
// callback
}
/**
* Registered fields
*/
add_settings_field( 'ev_settings_copyright_field', __( 'Copyright Name', 'evolutionary' ), 'ev_settings_copyright_field', 'evolutionary', 'ev_settings_general_options' );
add_settings_field( 'ev_settings_colors_field', __( 'Theme Color', 'evolutionary' ), 'ev_settings_colors_field', 'evolutionary', 'ev_settings_general_options' );
/**
* Fields Callbacks
*/
function ev_settings_copyright_field() {
$ev_options = get_option( 'theme_evolutionary_options' );
//var_dump( $ev_options );
?>
<input name="theme_evolutionary_options[copyright]" type="text" class="regular-text" value="<?php esc_attr_e( $ev_options['copyright'] ); ?>" />
<?php }
// Callback for colorscheme
function ev_settings_colors_field() {
$ev_options = get_option( 'theme_evolutionary_options' );
$color_schemes = ev_get_valid_color_schemes();
echo '<select name="theme_evolutionary_options[color_scheme]">';
foreach( $color_schemes as $value => $caption ) :
?>
<option value="<?php echo $value; ?>" <?php selected( $value, $ev_options['color_scheme'] ); ?>><?php echo $caption; ?></option>
<?php
endforeach;
echo '</select>';
}
} // ev_register_options
add_action( 'admin_init', 'ev_register_options' );
/**
* Creating options page HTML output
*/
function ev_admin_options_page() { ?>
<div class="wrap">
<?php if ( isset( $_GET['settings-updated'] ) ) {
echo "<div class="updated"><p>Theme settings updated successfully.</p></div>";
} ?>
<?php screen_icon(); ?>
<h2><?php _e( 'Theme Options', 'evolutionary' ); ?></h2>
<form action="options.php" method="post">
<?php
settings_fields( 'theme_evolutionary_options' );
do_settings_sections( 'evolutionary' );
?>
<input name="submit" type="submit" class="button-primary" value="<?php _e( 'Save Settings', 'evolutionary' ) ?>" />
<input name="reset" type="submit" class="button-secondary" value="<?php _e( 'Reset Settings', 'evolutionary' ) ?>" />
</form>
</div>
<?php }
function ev_options_validate( $input ) {
$ev_options = get_option( 'theme_evolutionary_options' );
$valid_input = $ev_options;
$ev_options['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
$ev_options['copytright'] = wp_kses_data( $ev_options['copyright'] );
return $valid_input;
}
3 Answers
@Mamaduka:
Here is why your settings aren’t updating. Your validation function is wrong. To wit:
function ev_options_validate( $input ) {
$ev_options = get_option( 'theme_evolutionary_options' );
$valid_input = $ev_options;
$ev_options['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
$ev_options['copytright'] = wp_kses_data( $ev_options['copyright'] );
return $valid_input;
}
You’re updating $ev_options, but returning $valid_input. You need to be updating $valid_input, not $ev_options.
Try this instead:
function ev_options_validate( $input ) {
$ev_options = get_option( 'theme_evolutionary_options' );
$valid_input = $ev_options;
$valid_input['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $ev_options['copyright'] );
return $valid_input;
}
See if that fixes your problem?
EDITED TO ADD:
Your next problem in the validation function is that you’re comparing $ev_options to/against itself, when you need to be evaluating $input against $valid_input.
Instead of this:
function ev_options_validate( $input ) {
$ev_options = get_option( 'theme_evolutionary_options' );
$valid_input = $ev_options;
$valid_input['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $ev_options['copyright'] );
return $valid_input;
}
Try this:
function ev_options_validate( $input ) {
$ev_options = get_option( 'theme_evolutionary_options' );
$valid_input = $ev_options;
$valid_input['color_scheme'] = array_key_exists( $input['color_scheme'], ev_get_valid_color_schemes() ) ? $input['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $input['copyright'] );
return $valid_input;
}
Specifically, change this:
$valid_input['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $ev_options['copyright'] );
To this:
$valid_input['color_scheme'] = array_key_exists( $input['color_scheme'], ev_get_valid_color_schemes() ) ? $input['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $input['copyright'] );
And then, I think, your options should work.
@TheDeadMedic:
The Settings API handles looking at any $POST data. That’s not the problem.
Regarding the default-settings updating on init, here’s my original, example code:
function oenology_options_init() {
// set options equal to defaults
global $oenology_options;
$oenology_options = get_option( 'theme_oenology_options' );
if ( false === $oenology_options ) {
$oenology_options = oenology_get_default_options();
}
update_option( 'theme_oenology_options', $oenology_options );
}
// Initialize Theme options
add_action('after_setup_theme','oenology_options_init', 9 );
And here’s Mamaduka’s code:
function ev_options_init() {
// Set options equal to defaults
global $ev_options;
$ev_options = ev_theme_settings_defaults();
if ( false === $ev_options ) {
$ev_options = ev_theme_settings_defaults();
}
update_option( 'theme_evolutionary_options', $ev_options );
}
add_action( 'after_setup_theme', 'ev_options_init', 9 );
Do you see the difference? There is a critical change from oenology_options_init() to ev_options_init(), to wit:
This:
global $oenology_options;
$oenology_options = get_option( 'theme_oenology_options' );
Versus this:
global $ev_options;
$ev_options = ev_theme_settings_defaults();
Thus, in ev_options_init(), the function never actually does anything, because of the change.