Accept AJAX call with serialized form data

I’m trying to pass a wordpress plugin some form data via ajax and it works just fine, unless the form data is serialized, then the server responds with an error message.
I’m stuck with this for days now, but I can’t get it to work.
What am I doing wrong, this can’t be so hard, right?

Here’s the error message:

Read More

call_user_func_array() expects parameter 1 to be a valid callback, function ‘process_request’ not found or invalid function name in X:xampphtdocstestsitewp-includesplugin.php on line 406

The AJAX call:

jQuery(document).ready(function($) {

nonce: whatever

//if i use this variable, it works fine 
var data = {action: 'process_request', add_my_data: 'whatever', 'my_data[name]':'whatever', my_nonce: nonce};

//if i use this variable, the server returns the above error .
//because .serialize() doesn't include the submit button's name
//and the form doesn't contain the name of the function to be called, i added them manually to the string. nonce is pulled from form.

var data2 ='action=process_request&add_my_data=whatever&' + $('#my-form').serialize();


$('.my_submit_button').click(function(event) {       
event.preventDefault(); 

jQuery.ajax({
type : 'post',
url : ajaxurl,
timeout: 25000,
data : //data (works) or data2 (doesn't work),
[...]

The strange thing is, the post data for ‘data2’ seems to be ok and has the same syntax like for ‘data’.

I controlled the post data with firebug:

for ‘data’:

action=process_request&add_my_data=whatever&my_data%5Bname%5D=whatever&my_nonce=1b444dd703 

for ‘data2’ (with the form serialized, the only difference I see is the referer):

action=process_request&add_my_data=whatever&my_data%5Bname%5D=whatever&my_nonce=1b444dd703&_wp_http_referer=%2Ftestsite%2Fadmin%2Ftestpage%2F

The PHP function that handles the request:

function process_request() {

    //nonce validation left out for readability

    if( isset ($_POST['add_my_data']) ) {
        $this->add_info_array('placeholder', 'Database updated');
    }
            //do some stuff here
            die();
        }
      add_action('wp_ajax_process_request', 'process_request');

UPDATE: The problem is the referer in the string that is created for ‘data2’. Check my comment below.

Related posts

2 comments

  1. When working with AJAX and Forms in WordPress I like to code in the ajax action to the form so serialize works out of the box. Actually I wrote an article on this last year: https://webdevstudios.com/2015/02/12/handling-ajax-in-wordpress/

    But, you’re here for answers, not a blog article, so here’s the brief part of it. You have three parts here, first is the HTML form. You can take advantage of serialize() by putting the action in a hidden form field, here’s an example:

    <form class="my_form">
        <?php wp_nonce_field( 'my_action_nonce' ); ?>
        <input type="hidden" name="action" value="my_action" />
        <!-- More fields here... -->
        <input type="submit" name="submit" value="Submit" class="submit_form_btn" />
    </form>
    

    Notice the hidden form field named action. Of course I kept the wp_nonce_field() since well, security issues.

    The second part is the actual jQuery, as stated previously, you don’t need to access AJAX via the original jQuery object since you already passed it in as $, but it doesn’t harm anything really, just bad practice.

    jQuery( document ).ready( function( $ ) {
        $( '.submit_form_btn' ).on( 'click', function( evt ) {
            // Stop default form submission
            evt.preventDefault();
            // Serialize the entire form, which includes the action
            var serialized = $( '.my_form' ).serialize();
            $.ajax( {
                url: ajaxurl, // This variable somewhere
                method: 'POST',
                data: serialized, // This is where our serialized data is
            } ).done( function( result ){
                // Handle the result here...
            } );
        } );
    } );
    

    I tried to comment the code as best I could, it should make more sense, but let me explain. First you stop the form submission by the preventDefault() method of the evt object, ( short for event ).

    You then serialize the form data and store it in a variable. I suppose you could shortcut it and simply drop that into the data object, but that’s up to you.

    The final part, well you need to see what you’re posting right? That’s where error_log and print_r come in handy, here’s how:

    <?php
    
    function handle_ajax() {
        // Here you verify your nonce
        if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'my_action_nonce' ) ) {
            // You can either return, or use nifty json stuffs
            wp_send_json_error();
        }
        // Here you should get ALL your data in a $_POST variable
        // or you can actually do someting like this then check your error log
    
        error_log( print_r( $_POST, 1 ) );
    
        // This will print out the ENTIRE $_POST variable to your debug.log if you have it
        // enabled, if not, it goes to your PHP error log
    
    }
    add_action( 'wp_ajax_my_action', 'handle_ajax' );
    

    Now that SHOULD handle your ajax for you, what you do with the data is up to you.

  2. Why are you using jQuery.ajax?

    When you define jQuery(document).ready(function($) {$ becomes your global jquery variable.
    WordPress jQuery noConflict Wrapper

    Your ajax should resemble this:

    $.ajax({
    type : 'post',
    url : ajaxurl,
    etc : ....
    

    Next, you can’t just pass a string of variables. You need to first define them into an object, and pass that.

    Try this:

    get_data = $('#my-form').serialize();
    var data = {action: 'process_request', add_my_data: get_data, my_nonce: nonce};
    

    Not sure about the serializing though… as I thought WordPress already did that during the ajax post process. You may need to research more there.

Comments are closed.