Posts form with AJAX request – Plugin development

Post without AJAX is working perfectly fine, but with AJAX, it’s
returning 0.

Simply put, that’s because your AJAX request doesn’t include the pp_submit input which is required by pp_html_process() — the callback for both regular and AJAX form submission.

I.e. As I said in the comments:

jQuery doesn’t serialize submit button value (see
here), which means the
pp_submit input was never submitted to the server, hence the if ( isset( $_POST['pp_submit'] ) ) returned false. So you just needed to
manually include pp_submit in your AJAX form data. However, your form contains a file input and therefore, you should instead use the
FormData
API

and not jQuery’s .serialize().

So for example, I’d do it like so:

function ajaxSubmit() {
    var formData = new FormData( this );

    // Yes, even when using FormData, you still need to manually include the pp_submit.
    formData.append( 'pp_submit', 1 );

    jQuery.ajax({
        type: 'POST',
        url: '/codeable/wp-admin/admin-ajax.php',
        data: formData,
        processData: false,
        contentType: false,
        success: function ( response ) {
            console.log( 'success', response );
        },
        error: function ( response ) {
            console.log( 'error!', response );
        }
    });

    return false;
}

And I’ve tested that with your exact PHP/HTML code, which means I simply replaced the above JS function, and then everything worked for me — the post was created successfully and the post thumbnail was also set correctly. However, I added wp_die() to prevent a 0 in the response. (see the 1st note below)

Additional Notes

  1. You should call wp_die() after you’ve set the post thumbnail, to exit the page and prevent WordPress from echoing a 0:

    // set the post thumbnail:
    // if ( $featured_image > 0 ) { ... your code here }
    
    // then call wp_die():
    if ( wp_doing_ajax() ) {
        echo 'Post created! ID: ' . $post_id;
        wp_die();
    }
    

    PS: I’d use the set_post_thumbnail() function to set the post thumbnail.

  2. I used url: '/codeable/wp-admin/admin-ajax.php' above because that’s what you used, but you really should localize your AJAX/JS parameters and then for example, use url: my_ajax_obj.ajax_url instead of hard-coding the admin-ajax.php URL/path into the url property.

  3. I strongly suggest you to use the modern WordPress REST API which:

    • Has a better error handling — e.g. with the admin-ajax.php endpoint, if your AJAX action isn’t registered correctly, you’d simply get a 400 Bad Request status with a 0 response; but with the REST API, if a route is not registered correctly, you’d see a human-readable error explaining what happened.

    • Has existing endpoints that one could simply use for creating posts, medias (attachment posts), terms, etc.

    • Allows you to create your own custom endpoint with a “pretty” URL (if permalinks are enabled on the site, of course) like https://example.com/wp-json/your-plugin/v1/pp-html-process and you could also easily set the endpoint to be public or be available to certain users/roles only.

    • Accepts many request formats including JSON payload (which is not supported by admin-ajax.php) and the response body/header also defaults to JSON.

    • … and many other features which you can find in the handbook here.