Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm trying to empty an option created with the Settings API and failing.

update_option ( 'my_option', '' ); appears to do nothing, whereas delete_option ( 'my_option' ); destroys the whole option causing other problems. I just want to empty the values and reset it.

I'm really clueless how to implement this correctly. Can anyone help? 50 point bounty up for grabs!

<?php
//Create the menus
add_action( 'admin_menu', 'tccl_menu' );
function tccl_menu() {  
    //add_menu_page: $page_title; $menu_title, $capability, $menu_slug, $function, $icon_url, $position
    add_menu_page( 'Control', 'Control', 'manage_options', 'tccl-main', 'tccl_menu_page_main', plugins_url( '/traffic-control/images/wp-icon.png' ), '2.2' );
    //add_submenu_page: $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function
    add_submenu_page( 'tccl-main', 'Domains', 'Domains', 'manage_options', 'tccl-domains', 'tccl_menu_page_domains' ); 
}

//Menu callback functions for drawing pages
function tccl_menu_page_main() {
    ?>
    <div class="wrap">
    <h2>Control</h2>
    <form action="options.php" method="post">
    <?php settings_fields( 'tccl_settings_main' ); ?>
    <?php do_settings_sections( 'tccl_settings_main' ); ?>
    <input name="Submit" type="submit" value="Save Changes" class="button-primary" />
    </form></div>
    <?php
}
function tccl_menu_page_domains() {
    $tccl_domains = get_option( 'tccl_settings_domains' );
    if ( $_POST['trigger'] ) {
        $p_delete_all = $_POST['delete_all'];
        $p_ids = $_POST['ids']; #Get IDs
        $p_deletes = $_POST['deletes']; #Get deletes
        if ( $p_delete_all ) {
            //unset( $tccl_domains );
            //delete_option( 'tccl_settings_domains' );
            foreach( $tccl_domains as $option ) {
                $option = false;
            }
            $tccl_domains = array ();
            update_option( 'tccl_settings_domains', $tccl_domains );
        } elseif ( is_array( $p_ids) ){
            foreach ( $p_ids as $id ) {
                if ( $p_deletes[$id] ) {
                    //unset( $tccl_domains[$id] );
                }
            }
        }
    }
    ?>
    <div class="wrap">
    <?php screen_icon( 'themes' ); ?>
    <h2>Control</h2>
    <form action="options.php" method="post">
    <?php settings_fields( 'tccl_settings_domains' ); ?>
    <?php do_settings_sections( 'tccl_settings_domains' ); ?>
    <input name="Add" type="submit" value="Add Domains" class="button-primary" />
    </form>
    <form action="" method="post">
    <input type="hidden" name="trigger" value="1">
    <h3>Live Domains</h3>
    <table class="widefat">
    <thead>
        <tr>
            <th><input type="checkbox" name="delete_all" value="1"></th>
            <th>Domain Name</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th><input type="checkbox" name="delete_all" value="1"></th>
            <th>Domain Name</th>
        </tr>
    </tfoot>
    <tbody>
        <?php
            print_r ( $tccl_domains );
            if ( is_array( $tccl_domains ) ) {
                foreach ( $tccl_domains as &$value ) {
                    echo '<tr><td><input class="large-text" type="checkbox"></td><td>'.$value['text_area'].'</td></tr>';
                }
            } else {
                echo '<tr><td colspan="2">No domains entered. Use the form above to add domains to this list.</td></tr>';
            }
        ?>
    </tbody>
    </table>
    <br />
    <input name="Delete" type="submit" value="Delete Domains" class="button-secondary" />
    </form>
    <script>
        jQuery('input[name=delete_all]').click(function () {
            if (jQuery(this).is(':checked')) {
            jQuery('tbody input[type=checkbox]').each(function () {
                jQuery(this).attr('checked', true);
            });
            jQuery('input[name=delete_all]').attr('checked', true);
            } else {
            jQuery('tbody input[type=checkbox]').each(function () {
                jQuery(this).attr('checked', false);
            });
            jQuery('input[name=delete_all]').attr('checked', false);
            }
        });
    </script>
    </div>
    <?php
}

//Settings
add_action( 'admin_init', 'tccl_admin_init' );
function tccl_admin_init() {
    // register_setting: $option_group, $option_name, $sanitize_callback
    register_setting( 'tccl_settings_main', 'tccl_settings_main', 'tccl_settings_main_validate' );
    register_setting( 'tccl_settings_domains', 'tccl_settings_domains', 'tccl_settings_domains_validate' );
    // add_settings_section: $id, $title, $callbak, $page
    add_settings_section( 'tccl_sections_main', 'Main Settings', 'tccl_sections_main_text', 'tccl_settings_main' );
    add_settings_section( 'tccl_sections_domains', 'Add Domains', 'tccl_sections_main_text', 'tccl_settings_domains' );
    // add_settings_field: $id, $title, $callback, $page, $section, $args
    add_settings_field( 'tccl_fields_main_input', 'Enter text here...', 'tccl_fields_main_input', 'tccl_settings_main', 'tccl_sections_main' );
    add_settings_field( 'tccl_fields_domains_input', 'Add domains to the list below. Multiple domains should be seperated by commas.', 'tccl_fields_domains_input', 'tccl_settings_domains', 'tccl_sections_domains' );
}

//Sections callback functions
function tccl_sections_main_text() {
    echo '<p>Enter your settings for the main options in the main section...</p>';
}

//Field callback functions
function tccl_fields_main_input() {
    //Get option 'text_string' value from the database
    $options = get_option( 'tccl_settings_main' );
    $text_string = $options['text_string'];
    //Echo the field
    echo "<input id='text_string' name='tccl_settings_main[text_string]' type='text' value='$text_string' />";
}
function tccl_fields_domains_input() {
    //Get option 'text_string' value from the database
    $options = get_option( 'tccl_settings_domains' );
    $text_area = $options['text_area'];
    //Echo the field
    echo "<textarea id='text_area' name='tccl_settings_domains[text_area]'>$text_area</textarea>";
}

//Settings callback functions (validation)
function tccl_settings_main_validate( $input ) {
    $valid['text_string'] = preg_replace( '/[^a-zA-Z]/', '', $input['text_string'] );

    if ( $valid['text_string'] != $input['text_string'] ) {
        //add_setting_error: $title, $id, $error_message, $class
        add_settings_error( 'tccl_fields_main_input', 'tccl_texterror', 'Incorrect value entered!', 'error' );
    }   

    return $valid;
}
function tccl_settings_domains_validate( $input ) {
    $options = get_option( 'tccl_settings_domains' );
    $options[] = $input;
    return $options;
}
?>
share|improve this question
    
I use that function all the time, where are you making that call to update_option, can i see more of your code? Ideally the code for the function it's sitting inside if it's sat inside a function.. (and if it's hooked onto something, details about what it's hooked onto would help to). –  t31os Jul 26 '11 at 15:42
    
I'm calling it from inside an add_submenu_page callback function. –  jnthnclrk Jul 26 '11 at 15:49
    
Is the usual value of the option a string or an array? Do you have several options? –  scribu Jul 26 '11 at 15:55
    
An array, I think a multi-dimensional one. Do I need to reset it with a new array? –  jnthnclrk Jul 26 '11 at 15:58
    
why not set the array with your default options? and what kind of problems is it causing? –  Bainternet Jul 26 '11 at 16:09
show 9 more comments

3 Answers

up vote 6 down vote accepted
+25

If you wrote your code correctly, then delete_option would be the correct way. The question isn't how to clear the option; the question is how to structure your code such that the "option does not exist" case is a valid case.

Think about it. The first time you start this code, that option isn't going to exist at all, right? Your code should be perfectly capable of handling that case, since it's the first thing the user is ever going to see.

get_option() accepts a default value if the option does not exist. So use that. If you had an empty array for the default, for example, you'd have code like this:

$options = get_option('whatever',array());

Assuming you're using the settings API, then you should use the isset function in if statements to account for the missing-field case. Something like this:

if (!isset($options['name'])) {
//... the option isn't set to something 
} else {
//... the option is set to something
}

And handle each case of actual use of the option accordingly.

share|improve this answer
    
This is actually an answer to a second question, that @trnsfmr should probably split out from the original question, into one of its own. –  Chip Bennett Aug 3 '11 at 15:29
    
FYI: Your comments in the isset example are round the wrong way. –  Mark Duncan Aug 3 '11 at 15:45
    
I'm struggling to understand how to make this answer work in my code. I think I should go back to the drawing board, thinking about using Chips post on the Settings API to work from. –  jnthnclrk Aug 3 '11 at 16:04
    
@trnsfrmr: The bottom line is that you need to do a delete_option and then fix whatever errors you get from having no option set at all. Because the very first time somebody runs your code, no option will be set. –  Otto Aug 3 '11 at 16:07
    
OK, delete option is working, but have failed on some other stuff. Time for a new question as Chip suggests. Hopefully you guys will still have some patience left... :) –  jnthnclrk Aug 3 '11 at 21:24
add comment

Do you want to unset just one option, or do you want to unset every option in the array?

If it's the former:

$tccl_domains = get_option( 'tccl_settings_domains' );

$tccl_domains['option_to_unset'] = false;

update_option( 'tccl_settings_domains', $tccl_domains );

If it's the latter:

$tccl_domains = get_option( 'tccl_settings_domains' );

foreach( $tccl_domains as $option ) {
    $option = false;
}
update_option( 'tccl_settings_domains', $tccl_domains );
share|improve this answer
    
Working on the latter, but update_option still seems to add more options rather than overwrite the existing... –  jnthnclrk Jul 26 '11 at 22:39
    
update_option still seems to add more options rather than overwrite the existing... I don't understand what you mean; can you clarify? –  Chip Bennett Jul 27 '11 at 2:41
    
Everytime update_option runs my array seems to get bigger. I'm wondering if my settings registration code is correct, I've added it to the question above... –  jnthnclrk Jul 27 '11 at 11:14
    
Would it be possible to post your entire settings-related code, either in your question, or in a Pastebin, or something? Trying to track down an issue like this would be much easier if we can see the entire code, in context. –  Chip Bennett Jul 27 '11 at 13:31
    
Let me see if I can clean it up and link it... –  jnthnclrk Jul 27 '11 at 13:53
show 2 more comments

first off, understand that every time you do a call to update_option() and delete_option() - not sure about delete_option() though - the validation function is called. And the way tccl_settings_domains_validate() is validating is what's causing the update_option() function to add more options:

 function tccl_settings_domains_validate( $input ) {
   $options = get_option( 'tccl_settings_domains' );
   $options[] = $input;
   return $options;
 }

what this function is doing is to take whatever is inside *tccl_settings_domains* and assign it to $options:

$options = get_option('tccl_settings_domains');

then add/push whatever is in $input into $options array. When the function returns $options (which basically "saves" the option) what's saved are the contents of options field plus the value of $input. Thus, the array gets bigger.

So, try this for a start:

function tccl_settings_domains_validate( $input ) {
    if( isset( $input['action'] ) && $input['action'] == 'add-domain' ){
        //add new value to $options array
        options = get_option( 'tccl_settings_domains' );
        $options[] = $input;
        return $options;
    }
    //return whatever value is passed.
    return $input;
}

then, in the Add Domain form (one that goes to options.php), add this hidden input <input name="tccl_settings_domains[action]" type="hidden" value="add-domain" />

This is the most straightforward solution I could think of that involves minimum amount of change in your code.

let me know if that works for you =)

share|improve this answer
    
Typo on line 4, should be $options... –  jnthnclrk Aug 1 '11 at 15:12
    
I'm afraid I can't get your suggestion to work. The if statement doesn't seem to ever be true. –  jnthnclrk Aug 1 '11 at 15:15
    
Also, from what I'm seeing the validation callback does not appear to run on delete_options(). –  jnthnclrk Aug 1 '11 at 21:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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