I am creating a theme options page but with object oriented approach. Every new instance of this object is a separate subpage. Rendering and all the options work fine (still in progress, but in a nutshell it works fine), except the AJAX save.

I have placed in my __construct method this

public function __construct( $subpage_name, $html_array ) {
    $this->subpage_name = $subpage_name;
    $this->html_array   = $html_array;
    add_action( 'admin_menu', array( $this, 'create_submenu_pages' ) );
    add_action( 'wp_ajax_settings_save', array( $this, 'all_settings_save' ) );

And I have a method

public function all_settings_save() {
    if ( isset( $_POST['data'], $_POST['settings_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['settings_nonce'] ), 'settings_nonce_action' ) && '' !== $_POST['data'] ) { // Input var okay.
        $settings = json_decode( sanitize_text_field( wp_unslash( $_POST['data'] ) ) ); // Input var okay.
        update_option( str_replace( ' ', '_', strtolower( $this->subpage_name ) ), $settings );

When I click on the save button, my ajax works because I can see the data in the inspector (Network tab and then admin-ajax.php), for instance it shows that the form data is:

  "settings": {
    "header_title": "Testing",
    "logo": "",
    "retina_logo": "",
    "retina_logo_width": "23",
    "retina_logo_height": "",
    "transparent_logo": "",
    "transparent_retina_logo": "",
    "transparent_retina_logo_width": "",
    "transparent_retina_logo_height": "",
    "background_image": ""

So this should be stored in my database under, if it's 'Header Settings' page then it's header_settings option in my wp_options table. but when I reload the page nothing is inserted, because I have no row called header_settings present in the wp_options table.

I thought that the validation checks are failing, so I've removed them, but I still don't get a thing.

What am I doing wrong?

  • Enable debug log (you also need WP_DEBUG set to true), run the code, check wp-content/debug.log, report back if you get anything Sep 7, 2016 at 10:31
  • I have both define('WP_DEBUG', true); and define('WP_DEBUG_LOG', true); but I don't have debug.log or error.log. I need to check the settings of my server
    – dingo_d
    Sep 7, 2016 at 11:51
  • I checked my error logs on server, and there is not a single error thrown :\
    – dingo_d
    Sep 7, 2016 at 12:19
  • With the same settings in place, try some debug statements with error_log( $message ) - maybe one at the start of the function error_log( 'Running handler...' ), one inside the if, and one just before wp_die - you'll then know if a) it's firing at all and b) if the code is running as you expected Sep 7, 2016 at 12:30
  • Added it, and I get nothing. Is it possible that because my ajax action is being called in the __construct() method? Should I define a separate method and call it in the construct or something like that?
    – dingo_d
    Sep 8, 2016 at 5:19

1 Answer 1


Found the issue. First I added

ini_set('error_reporting', E_ALL);
ini_set('error_log', dirname(__FILE__) . '/error_log.txt');

along the

define('WP_DEBUG', TRUE);

in my wp-config.php, this writes the errors, notices and warnings in the error_log.txt in the root folder (I don't know why I haven't thought of that in the first place).

Then I saw the errors - I used json_decode instead of wp_json_encode to encode my settings as a string before storing it in my option.

There is this weird issue of name being not of the subpage, but I'll get to that now.

Thanks to TheDeadMedic for suggesting the error_message() method of finding out if the code works or not. This will help with any AJAX debugging in the future.

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.