I'm following @Otto's tutorial on Settings API. I managed to save the plugin settings into the options table, but by any means can't save any fields.

*   Add Settings SubMenu
*   Thanks to: Otto
*   Following: http://ottopress.com/2009/wordpress-settings-api-tutorial/
function plugins_settings_page() {
        'my-page-slug',       //$parent_slug
        'Plugin Settings',                 //$page_title
        'Plugin Settings',                 //$menu_title
        'manage_options',                   //$capability
        'plugin-settings',                 //$menu_slug
        'plugins_settings_page_callback'    // callback function

add_action('admin_menu', 'plugins_settings_page');

function plugins_settings_page_callback() {
    <div class="wrap">
        <h2>Plugin Settings</h2>
        <?php settings_errors(); ?>
        <form action="options.php" method="post">
            <?php settings_fields('plugin_options'); ?>
            <?php do_settings_sections('plugin_settings'); ?>
            <p class="submit">
                <?php submit_button(); ?>
    </div> <!-- .wrap -->

function plugin_options_init(){

    if( false == get_option( 'plugin_settings' ) ) {
        add_option( 'plugin_settings' );

        'plugin_options',          // Option group*
        'plugin_options',          // Option Name*
        'plugin_options_validate'   // Sanitize Callback Function
        'plugin_general',              // ID/Slug*
        'General Settings',            // Name*
        'plugin_section_callback',      // Callback*
        'plugin_settings'                    // Page on which to add this section of options*
        'plugin_function_activation',       // ID*
        'Activate Plugin Function',        // Title*
        'plugin_setting_field',    // Callback Function*
        'plugin_settings',                   // Page (Plugin)*
        'plugin_general'               // Section

// add the admin settings and such
add_action( 'admin_init', 'plugin_options_init' );

function plugin_section_callback() {
    //echo '<p>Main description of this section here.</p>';

function plugin_setting_field() {
    $options = get_option('plugin_options');
    echo "<input name='plugin_options[plugin_settings_field]' id='plugin_function_activation' type='checkbox' value='1' ".checked( 1, $options['plugin_settings_field'], false ) . " />";

/*// validate our options
function plugin_options_validate($input) {
    $options = get_option('plugin_options');
    $options['text_string'] = trim($input['text_string']);
    if(!preg_match('/^[a-z0-9]{32}$/i', $options['text_string'])) {
        $options['text_string'] = '';
    return $options;

Issues I assumed and checked are:

  1. I'm using add_submenu_page() where Otto used add_options_page()
  2. I added the following portion extra:

    if( false == get_option( 'plugin_settings' ) ) {
        add_option( 'plugin_settings' );
  3. Where I used underscore-separated value: do_settings_sections('plugin_settings'), Otto used single value do_settings_sections('plugin')

  4. I'm using a checkbox, where Otto used a textbox

My approaches the above mentioned situations:

  1. Found no real difference except the parent slug, so it's not causing the problem
  2. Without that block I couldn't save anything into the db, so I added this
  3. It's not causing problem as I can put data into db even with my value
  4. For the name="" parameter both are the same, so saving won't be affected

And here's the current state of db, option_value is empty: options table for plugin settings

What's causing me the pain?

  • You should activate the WP_DEBUG constant in wp_config.php There are a lot of typos such as unwanted "s" and undefined indexes.
    – JMau
    Commented Sep 18, 2014 at 19:22
  • @JMau both the WP_DEBUG and SCRIPT_DEBUG is true in my case, but no such warning is displayed. Could you please point the unwanted s and where are those undefined indexes? I actually couldn't see 'em. :( Commented Sep 19, 2014 at 2:31
  • Really? Ok. In your code you got "plugin_setting_field" and "plugin_settings_field", doesn't feel right.
    – JMau
    Commented Sep 19, 2014 at 17:52
  • @JMau plugin_setting_field is nothing but a callback function, it can be anything, even xyz()... and plugin_settings_field is the option name with which I'm storing data into Options. So all of them are good - aren't they? Commented Sep 21, 2014 at 3:55
  • Oh yes, read that too fast sorry.
    – JMau
    Commented Sep 28, 2014 at 20:37

1 Answer 1


You appear to have the validation function commented out. Try this one for testing only:

function plugin_options_validate($input) {
   return $input;

Now do your options save?

Validation functions are not optional. They take the settings, validate them, and return the valid ones. If you don't have a validation function then the settings won't be returned from it, and therefore won't be saved.

The function I just gave is horrifically unsafe, because it does no validation. You need to have code here to check the incoming settings, make sure they are valid, and to then return the valid ones. Without this, settings cannot be saved.

  • Thanks a lot for the tips, and it's saving data. BTW I commented the function out because I followed the Codex, it's saying the $sanitize_callback function is optional, so I thought, even if I omit the line from the register_setting() function, it should work. But what you said, it's mandatory, so should I edit the Codex page? Commented Sep 19, 2014 at 2:37
  • 1
    Technically, yes, if you leave out that third parameter to the register_setting call, then no validation callback is necessary. You should never do that, validation is an important security step.
    – Otto
    Commented Sep 19, 2014 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.