I finally managed to create working validation callback for Settings API with big help of Chip Bennet, there's only one glitch that I'm not sure how to fix.

Here's the foreach loop from my validation function:

    foreach ($settings as $setting) {
        $id = $setting['id'];  
        $type = $setting['type'];
        $option = get_option('XX_theme_settings');

       if($type == 'textarea') {
           $valid_input[$id] = wp_filter_nohtml_kses($input[$id]);

I'm looping trough many $settings and code above doesn't work like expected, if I have 10 textareas within my settings and I'm editing only one textarea the $input[$id] for the other 9 will be NULL and they're going to be instantly erased.

I was trying to solve this doing additional input checks like:

//if there is no input for given field leave the old value
if($type == 'textarea' && empty($input[$id])) {
   $valid_input[$id] = wp_filter_nohtml_kses($option[$id]);

//if there's input sent change setting's value
else if($type == "textarea" && !empty($input[$id])) {
   $valid_input[$id] = wp_filter_nohtml_kses($input[$id]);

And it basically works, but makes it impossible to erase options. For example, if I have option called "welcome_text" with value "Welcome folks" attached, I can't erase all the symbols and leave this field empty, because the first if statement is being fired. So "welcome_text" value could be "Welcome fol" or "W" but never " ".

I can see my first approach works pretty well in here, I'm not sure why.

Thanks :)

1 Answer 1


If you have an options page (which should be inside one form), then all data is sent from that form, regardless of whether or not the option has been changed.

The array received for validation is the data received from (your part of) the form. If the data is 'empty' it is because the data wasn't sent. Normally this would be because the user has deliberately not sent any data (i.e. emptied a text-area).

If you are trying to store options from different pages in one array then you are going to need to determine if blank data actually was deliberate or instead because wasn't sent because it wasn't on the page that has been submited.

Handling expected data only

Really what you need to determine is what data are you expecting to receive? In your case this will depend on what page you are submitting data from:

//The 'ids' of data that is expected on the respective page
$page1_options = array('textarea_on_page_1','checkbox_1','another_textarea_1');
$page2_options = array('someinput_2','another_textarea');

//An array of arrays of option names the plugin accepts:
$expected =array('page1'=>$page1_options,'page2'=>$page2_options);

Then if submitting data from page 1, the data we expect to receive is $expected['page1'].

So we only validate those options and filter everything else out so that we end up with $valid_input which contains all and only the keys listed $page1_options. Then we take the current options, merge them with this new valid input to get the new settings array:

$option_array = get_option('XX_theme_settings');
$option_array = array_merge($option_array,$valid_input);
//Return this $option_array to be saved to database

Determining the page

To determine what page is being sent, on each page add another 'option' which is in fact hidden input with value set to the page ID I referred to above (e.g. 'page1'). This will be sent with the options.

A better way

A more straightforward way would to have the settings for each page saved as a separate row in the database (so you have X (arrays of) options for X pages).

  • Stephen Harris, well, I was still trying to display multiple forms (sections) per admin page and it was the main issue, now everything works fine and I'm not even doing array_merge - and by the way I'm not sure if I should, because Chip Bennet said I should never do that with Settings API. Anyways thanks a lot! :) Mar 2, 2012 at 14:38
  • Any reason why you can't have one big form? (You can still style to appear as multiple sections. Then (any) submit button would send the whole form and make life a lot easier Mar 3, 2012 at 0:32
  • Re. merging arrays - it is fine to merge arrays when all the arrays have been sanitised and checked. In this case one was, and the other was straight from the database may be considered to be ok. Mar 3, 2012 at 0:33

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.