1

What happens, when I click Save Changes on a option page, which was created by add_menu_page()? Where is the submitted data stored before the database transmission?

A print_r($_REQUEST) returns only the two $_GET parameters page and settings-updated.

I've checked the manual for add_settings_field and there is only the following hint:

... the saving will be done behind the scenes.

Background

I'd like to optimize my process of creating a plugin settings page. I've already jumped on the WP Settings API with add_settings_section and add_settings_field long time ago, but it feels a bit uncomfortable to create a new callback function every time. So instead of creating the specific field/section code inside a callback, I'd like to create the complete settings page with Zend_View. All input fields would be created with Zend_Form and also attached to the view. In the end, the callback of add_menu_page() will return the rendered View-Object instead of the normal HTML output.

The HTML is stored inside a View-Template, located in views/pages/admin/ (e.g. default.phtml).

The basic principle is already working I'm very happy with the result. Due to the use of Zend_View, I've to do the saving on my own. But WordPress seems to delete the submitted $_POST array. If I debug the output after a successfull form submission, only the two $_GET params above are set.

I've also attached the output of the function settings_fields() to the view, which generates the required hidden fields (option_page, action, _wp_nonce).

Any ideas?

2 Answers 2

4

You only need one callback function, as defined in your call to register_setting() (Codex ref.):

register_setting( $option_group, $option_name, $sanitize_callback );

Thus, all options are contained in an array, in a single database entry, $option_name.

Then, the callback function is passed the $input variable that holds all of the form-submitted data, the function manipulates/sanitizes those data, and returns the sanitized output:

function mytheme_sanitize_callback( $input ) {
    // sanitization functions go here
    return $sanitized_output;
}

So: one database entry, as an array of options; and one sanitization callback for form-submitted user data.

For more help, you might reference this tutorial.

2
  • 1
    And it should be noted if you ever use the settings API, you should always be passing register_setting the callback parameter and validating your input, or at the least passing it the name of an existing function to sanitize the input.
    – t31os
    Commented Jul 8, 2011 at 15:27
  • @Chip Thanks for your long tutorial. Very informative. But unfortunately this was indeed my fault to include the hidden fields generated by register_setting to my Zend_View object.
    – Roman
    Commented Jul 8, 2011 at 17:32
0

I've finally found my fault.

The "problem" with Zend_View and Zend_Form is, that you have to check and save the submitted settings by yourself. But if you register a sanitize hook with register_setting(), WordPress will indeed not return any $_POST array and will immediatly submit the data to the defined option in the database.

The solution was to remove the call to register_setting() completely. I've also removed the call to settings_field() and set the hidden fields manually in the Zend_Form object.

$form = new Zend_Form();
$form->setAction('options.php?page=' . $this->getMenuSlug())
     ->setMethod('post');

$wpnonce = $form->createElement('hidden', '_wp_nonce');
$wpnonce->setValue(wp_create_nonce($this->getMenuSlug()));

The method $this->getMenuSlug() will return the id of the current generate admin page used in add_page_menu().

The last part was to do the form validation before echoing the Zend_View object. This is done in the renderView() method, which will be called as callback in add_menu_page().

public function renderView() {
    try {
        if($_POST['submit']) {
            // Check wp nonce
            if(!wp_verify_nonce($_POST['_wp_nonce'], $this->getMenuSlug())) {
                wp_die(__('Nonce incorrect!'));
            } else {
                if($this->_form->isValid($_POST)) {
                    echo '<div id="message" class="updated fade"><p><strong>' . __('Settings saved.') . '</strong></p></div>';
                    foreach ($this->_form->getElements() as $element) {
                        if(in_array($element->getName(), $this->_skipElements)) {
                            continue;
                        }

                        Webeo_Option::getInstance()->setValue($element->getName(), $element->getValue());
                    }

                    Webeo_Option::getInstance()->commit();
                } else {
                    echo '<div id="message" class="error fade"><p><strong>' . __('Errors occured.') . '</strong></p></div>';
                }
            }
        }

        echo $this->_form->render($this->_view);
        //echo $this->_view->render($this->getViewTemplate());
    } catch (Zend_View_Exception $e) {
        echo $e->getMessage();
    }
}

The Webeo_Option is just an object storage and could be replaced with update_option().

1
  • I would strongly recommend ditching Zend View, and implementing your WordPress settings in a way that is consistent with WordPress coding practices and standards. register_setting() exists for a reason. Commented Jul 9, 2011 at 3:32

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.