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?
While you are using Settins API, that’s why you don’t need to use
update_option
oradd_option
functions. Settings API would handle that by self.There were few issues that’s why your code is not working.
1.
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:2.
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:
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 callget_option
function with the option name that you registered with theregister_setting
function. And that would be like: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 asoption_name
in theregister_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:Replace your
add_settings_section
function with this one:Replace all
get_option
function with this one:$options = wpa_options(‘plugin_options’);
And finally add this new code:
Put it all together:
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.
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
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.
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)
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 whySecond problem is that the
register_setting()
function does not actually create the settings options in the database. You need to do something like this: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.