1

have a simple plugin that inserts text (a Google ad) partway through the content of a single post. I'm trying to create a settings page that will let users change the ad code, and change after which paragraph the ad appears.

I have spent all day reading tutorials and code, and I have a lovely settings page, but I can't figure out how to get it to actually save the data. I'm mostly following the example in Professional WordPress Plugin Development.

Here's what I have:

<?php
// add plugin options
add_option( 'wpa_ad_insert_paragraph', '2' );
add_option( 'wpa_ad_insert_adcode', 'ad code goes here');

// update options
update_option( 'wpa_ad_insert_paragraph', $_POST['wpa_ad_insert_paragraph'] );
update_option( 'wpa_ad_insert_adcode', $_POST['wpa_ad_insert_adcode'] );

// Add a menu for our option page
add_action('admin_menu', 'wpa_ad_insert_add_page');
function wpa_ad_insert_add_page() {
    add_options_page( 'Ad Insertion', 'Ad Insertion', 'manage_options', 'wpa_ad_insert', 'wpa_ad_insert_option_page' );
}

// Draw the option page
function wpa_ad_insert_option_page() {
    ?>
    <div class="wrap">
        <?php screen_icon(); ?>
        <h2>Ad Insertion</h2>
        <form action="options.php" method="post">
            <?php settings_fields('wpa_ad_insert_options'); ?>
            <?php do_settings_sections('wpa_ad_insert'); ?>
            <input name="Submit" type="submit" value="Save Changes" />
        </form>
    </div>
    <?php
}

// Register and define the settings
add_action('admin_init', 'wpa_ad_insert_admin_init');
function wpa_ad_insert_admin_init(){
    register_setting(
        'wpa_ad_insert_options',
        'wpa_ad_insert_options',
        'wpa_ad_insert_validate_options'
    );
    add_settings_section(
        'wpa_ad_insert_main',
        'Ad Insertion Settings',
        'wpa_ad_insert_section_text',
        'wpa_ad_insert'
    );
    add_settings_field(
        'wpa_ad_insert_paragraph',
        'Ad will appear after paragraph number:',
        'wpa_ad_insert_paragraph_setting',
        'wpa_ad_insert',
        'wpa_ad_insert_main'
    );
    add_settings_field(
        'wpa_ad_insert_adcode',
        'Ad code:',
        'wpa_ad_insert_adcode_setting',
        'wpa_ad_insert',
        'wpa_ad_insert_main'
    );
}

function wpa_ad_insert_paragraph_setting() {
    $options = get_option('wpa_ad_insert_paragraph');
    $items = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20");
    echo "<select id='wpa_ad_insert_paragraph' name='plugin_options[wpa_ad_insert_paragraph]'>";
    foreach($items as $item) {
        $selected = ($options['wpa_ad_insert_paragraph']==$item) ? 'selected="selected"' : '';
        echo "<option value='$item' $selected>$item</option>";
    }
    echo "</select>";
}

function wpa_ad_insert_adcode_setting() {
    $options = get_option('wpa_ad_insert_adcode');
    echo "<textarea id='wpa_ad_insert_adcode' name='plugin_options[wpa_ad_insert_adcode]' rows='7' cols='50' type='textarea'>{$options['wpa_ad_insert_adcode']}</textarea>";
}


function wpa_insert_ad($content) {
    $paragraphAfter = get_option('wpa_ad_insert_paragraph');
    $ad = get_option('wpa_ad_insert_adcode');
    if( is_single() && is_main_query() ) {
        $content = explode("</p>", $content);
        for ($i = 0; $i <count($content); $i++ ) {
            if ($i == $paragraphAfter)   
            echo $content[$i] . "</p>";
        }
    }   
    return $content;
}
add_filter('the_content', 'wpa_insert_ad');
?>

This code creates a settings page, but when I save the settings page, nothing happens (well, I get the yellow bar saying my settings have been saved, but the information is definitely not getting saved in the database.

What am I missing here?

4
  • I'll add some more specific questions to make this easier to answer. 1 - I don't need to create options.php, correct? It's my understanding that the magic of the Settings API should take care of everything, and options.php is built in.
    – Morgan Kay
    Dec 13, 2012 at 17:21
  • Another question... none of the tutorials I followed included the "add_option" and "update_option" stuff - I added that in because it seemed necessary. Is it? Should it be done differently?
    – Morgan Kay
    Dec 13, 2012 at 17:36
  • And a third question... At the top, I have add_option( 'wpa_ad_insert_paragraph', '2' );, and in the final function at the bottom I use $paragraphAfter = get_option('wpa_ad_insert_paragraph');, but I never get the value I expect - I never get the default "2" or the value I save on the settings page. In the database, that value is set to "3", and I'm not sure how that value got saved or how to change it.
    – Morgan Kay
    Dec 13, 2012 at 17:38
  • those add_option and update_option calls shouldn't be there
    – Tom J Nowell
    Oct 26, 2015 at 19:56

4 Answers 4

3

While you are using Settins API, that's why you don't need to use update_option or add_option functions. Settings API would handle that by self.

There were few issues that's why your code is not working.

1.

add_settings_section(
    'wpa_ad_insert_main',
    'Ad Insertion Settings',
    'wpa_ad_insert_section_text',
    'wpa_ad_insert'
);

3rd parameter is the callback function. Since, you don't need this function therefore just add __return false as the callback. Then your code for this function would be like:

add_settings_section(
    'wpa_ad_insert_main',
    'Ad Insertion Settings',
    '__return_false',
    'wpa_ad_insert'
);

2.

register_setting(
    'wpa_ad_insert_options',
    'wpa_ad_insert_options',
    'wpa_ad_insert_validate_options'
);

Look at the above code. Since second parameter is the option name, that's why you have to use this option name when you want to retrieve the option from database. Instead of calling that option name, you called two option names listed below:

$options = get_option('wpa_ad_insert_paragraph');
$options = get_option('wpa_ad_insert_adcode');

Since you used another option name in the register_setting function, that's why you were failed to retrieve the option into the database. You should have call get_option function with the option name that you registered with the register_setting function. And that would be like:

$options = get_option('wpa_ad_insert_options');

3. But still the data is not being saved into the database, right? Because, you used plugin_options as the name of your form input and textarea. Since you are using wordpress Settings API, that's why you should have use the same name that you registered as option_name in the register_setting function.

So, you need to fixed few things to make this code usable. I modified few lines of your code and that works. Replace your register_setting function with this one:

register_setting(
    'wpa_ad_insert_options',
    'plugin_options',
    'wpa_ad_insert_validate_options'
);

Replace your add_settings_section function with this one:

add_settings_section(
    'wpa_ad_insert_main',
    'Ad Insertion Settings',
    '__return_false',
    'wpa_ad_insert'
);

Replace all get_option function with this one: $options = wpa_options('plugin_options');

And finally add this new code:

function wpa_options() {
    $default = array(
        'wpa_ad_insert_paragraph' => 1,
        'wpa_ad_insert_adcode' => ''
        );
    return get_option('plugin_options', $default);
}

Put it all together:

// Add a menu for our option page
add_action('admin_menu', 'wpa_ad_insert_add_page');
function wpa_ad_insert_add_page() {
    add_options_page( 'Ad Insertion', 'Ad Insertion', 'manage_options', 'wpa_ad_insert', 'wpa_ad_insert_option_page' );
}

// Draw the option page
function wpa_ad_insert_option_page() {
    ?>
    <div class="wrap">
        <?php screen_icon(); ?>
        <h2>Ad Insertion</h2>
        <form action="options.php" method="post">
            <?php settings_fields('wpa_ad_insert_options'); ?>
            <?php do_settings_sections('wpa_ad_insert'); ?>
            <input name="Submit" type="submit" value="Save Changes" />
        </form>
    </div>
    <?php
}

// Register and define the settings
add_action('admin_init', 'wpa_ad_insert_admin_init');
function wpa_ad_insert_admin_init(){
    register_setting(
        'wpa_ad_insert_options',
        'plugin_options',
        'wpa_ad_insert_validate_options'
    );
    add_settings_section(
        'wpa_ad_insert_main',
        'Ad Insertion Settings',
        // 'wpa_ad_insert_section_text',
        '__return_false',
        'wpa_ad_insert'
    );
    add_settings_field(
        'wpa_ad_insert_paragraph',
        'Ad will appear after paragraph number:',
        'wpa_ad_insert_paragraph_setting',
        'wpa_ad_insert',
        'wpa_ad_insert_main'
    );
    add_settings_field(
        'wpa_ad_insert_adcode',
        'Ad code:',
        'wpa_ad_insert_adcode_setting',
        'wpa_ad_insert',
        'wpa_ad_insert_main'
    );
}

register_setting(
    'wpa_ad_insert_options',
    'plugin_options',
    'wpa_ad_insert_validate_options'
);

function wpa_ad_insert_paragraph_setting() {
    $options = wpa_options('plugin_options');
    $items = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20");
    echo "<select id='wpa_ad_insert_paragraph' name='plugin_options[wpa_ad_insert_paragraph]'>";
    foreach($items as $item) {
        $selected = ($options['wpa_ad_insert_paragraph']==$item) ? 'selected="selected"' : '';
        echo "<option value='$item' $selected>$item</option>";
    }
    echo "</select>";
}

function wpa_ad_insert_adcode_setting() {
    $options = wpa_options('plugin_options');
    echo "<textarea id='wpa_ad_insert_adcode' name='plugin_options[wpa_ad_insert_adcode]' rows='7' cols='50' type='textarea'>{$options['wpa_ad_insert_adcode']}</textarea>";
}


function wpa_insert_ad($content) {
    $paragraphAfter = get_option('wpa_ad_insert_paragraph');
    $ad = get_option('wpa_ad_insert_adcode');
    if( is_single() && is_main_query() ) {
        $content = explode("</p>", $content);
        for ($i = 0; $i <count($content); $i++ ) {
            if ($i == $paragraphAfter)   
            echo $content[$i] . "</p>";
        }
    }   
    return $content;
}
add_filter('the_content', 'wpa_insert_ad');

function wpa_options() {
    $default = array(
        'wpa_ad_insert_paragraph' => 1,
        'wpa_ad_insert_adcode' => ''
        );
    return get_option('plugin_options', $default);
}
0
0

I started all over using the Plugin Options Starter Kit plugin - http://www.presscoders.com/plugins/plugin-options-starter-kit/. This is a nice plugin. It's actually not really a plugin at all, it's just a plugin settings page with all the options you might want to use, so it's easy to copy/paste/cut/configure it to do what you want. I'm still not sure why my code above doesn't work (other than the fact that the version pasted above doesn't have the validation function, but adding that back in didn't fix the problem), so if anyone wants to tell me what else I needed to do to get this to work, I'd love to know.

1
0

The problem is the location in the code where you are coding the update .

Once you submit the form, options.php is being loaded and your plugin with it. At that point the options are updated from the post data. Then you are redirected back to your settings page, and your code get executed again, but this time there is no values in $_POST so your options are filled with some empty value.

If you use the settings API, you should leave the updating of the options to it, and even if not your update code should have been

if (isset($_POST['wpa_ad_insert_paragraph'] )) {
  pdate_option( 'wpa_ad_insert_paragraph', $_POST['wpa_ad_insert_paragraph'] );
  update_option( 'wpa_ad_insert_adcode', $_POST['wpa_ad_insert_adcode'] );
}

Now add_option is almost an alias to update_option, if the option exists it will behave like update_option, and if update_option is called when the option do not exist the option will be added. Therefor you need to check the non existence of the option before initializing it.

if (!get_option('wpa_ad_insert_paragraph')) {
  add_option( 'wpa_ad_insert_paragraph', '2' );
  add_option( 'wpa_ad_insert_adcode', 'ad code goes here');
}

get_option returns false when the option do not exists (but you need to be careful if false is one of the values your option can have)

4
  • When I first wrote this code, I didn't have the add_option and update_option stuff at all - I added it later because I thought it might make the form work. If I understand you correctly, if I didn't have the add_option and update_option in there at all, it should work, right? But it doesn't work, even if I take those out.
    – Morgan Kay
    Dec 14, 2012 at 17:04
  • Did your code include the wpa_ad_insert_validate_options function? I can't find it in the snippet Dec 14, 2012 at 17:16
  • This snippet doesn't have it, but even when I had that function in there, it wasn't working.
    – Morgan Kay
    Dec 14, 2012 at 20:20
  • Then you can assume there was bug there as well Dec 14, 2012 at 22:30
0

You have a few issues here it seems. First issue being that you should separate the output from the logic. Basically, the admin_init action you are calling is probably not being executed correctly because it is too late in the timeline. See this similar question here and the answer: Can't output do_settings_sections . Can't understand why

Second problem is that the register_setting() function does not actually create the settings options in the database. You need to do something like this:

    // Register and define the settings
    add_action('admin_init', 'wpa_ad_insert_admin_init');
function wpa_ad_insert_admin_init(){

    // This will make sure your options are created in the database
    if( false === get_option( 'wpa_ad_insert_options' ) ) {
        add_option( 'wpa_ad_insert_options' );
    }

    register_setting(
        'wpa_ad_insert_options',
        'wpa_ad_insert_options',
        'wpa_ad_insert_validate_options'
    );

    ...

The check at the beginning of the function will make sure you are creating the option to save the settings to. There was a similar issue here: Why won't register_setting() create a setting?

As @MarkKaplun said in his answer you should also remove the update_option stuff and let WordPress handle that for you.

When you use register_setting() the second argument is the option in the database you want it to save to, that is why you need to make sure the option exists before registering the setting.

At my first glance the issues I mentioned above look like the biggest ones, but there may be others after you get those fixed and we can work from there.

Your Answer

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

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