I have been using settings API for my plugins for some time and it used to work well. Now it is broken and I can not figure out why. Apparently, the option validation function is not even called. Form data is properly sent and received, though. (Both figured out by echo resp print_r debugging.)

I boiled down a (hopefully) minimal yet runnable example that retains both features of what I do and structure of how I do it:


Plugin Name: My Plugin
Plugin URI: http://wordpress.org/extend/plugins/myplugin/
Description: Example plugin.
Version: 1.0
Author: Your Name
Author URI: http://your.site
License: GPL2


class MyPlugin extends Plugin {

  function __construct() {
    parent::__construct(array('name' => 'myplugin',
                              'prettyName' => 'My Plugin',
                              'mainFile' => __FILE__));

  function activate() {
    if ( !get_option($this->name) ) {
      $options = array( 'test' => 'testwert' );
      add_option($this->name, $options);

  function deactivate() {}

  function options_validate($input) {
    $options = get_option($this->name);

    $options['test'] = empty($input['test']) ? $options['test'] : $input['test'];

    return $options;

  function setup_settings() {

new MyPlugin();


if ( !class_exists('Plugin') ) {

abstract class Plugin {
  protected $name;
  protected $prettyName;
  protected $mainFile;
  private $hasOptions = true;
  protected $options;

  function __construct($props, $hasOptions = true) {
    $this->name = $props['name'];
    $this->prettyName = $props['prettyName'];
    $this->mainFile = $props['mainFile'];
    $this->hasOptions = $hasOptions;

    if ( $hasOptions ) {
      if ( is_admin() ) {
        // Register Options Page
        add_action('admin_menu', array(&$this, 'admin_menu_init'));
        // Register settings
        add_action('admin_init', array(&$this, 'setup_settings'));

      $this->options = get_option($this->name);

    register_activation_hook($this->mainFile, array(&$this, 'activate'));
    register_deactivation_hook($this->mainFile, array(&$this, 'deactivate'));

  function admin_menu_init() {
    add_options_page($this->prettyName.' -- Options', $this->prettyName, 'manage_options', basename($this->mainFile), array(&$this, 'options_page'));

  abstract function options_validate($input);

  function setup_settings() {
    register_setting($this->name, $this->name, array(&$this, 'options_validate'));

  function options_page() { ?>
    <div class="wrap">
      <h2><?php echo $this->prettyName; ?> &ndash; Settings</h2>
      <form action="" method="post">
        <?php submit_button(); ?>
        <?php settings_fields($this->name); ?>
        <?php do_settings_sections($this->name); ?>
        <?php submit_button(); ?>
    </div> <?php

  abstract function activate();

  abstract function deactivate();




class MyPluginCallbacks {
  private $name = null;
  private $options = null;

  function __construct($name, $options) {
    $this->name = $name;
    $this->options = $options;

  function general_text() {
    echo 'A simple options page demonstration';

  function test() {
    echo "<input id='sanitisation' name='{$this->name}[test]' type='text' value='{$this->options['test']}'/>\n";
    echo "<br /><small>A simple test value.</small>";

$callbacks = new MyPluginCallbacks($this->name, $this->options);

add_settings_section('general', 'General', array(&$callbacks, 'general_text'), $this->name);
add_settings_field('test', 'Test Value:', array(&$callbacks, 'test'), $this->name, 'general');


Can be reproduced on WP 3.3 and the latest build via beta test plugin. There are no visible debug messages (WP_DEBUG is enabled).

Edit: Something that changed is the options page. It used to be options.php but that did no longer work. Now it is options-general.php.

1 Answer 1

<form action="" method="post">

should be

<form action="options.php" method="post">

Must have overcompensated for something there.

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.