1

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:

call_user_func_array() expects parameter 1 to be a valid callback, function 'process_request' not found or invalid function name in X:\xampp\htdocs\testsite\wp-includes\plugin.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.

  • You need to show a bit more of code, where's the hook? – brasofilo Oct 19 '13 at 23:13
  • it's there, i just didn't include it above (included it now). as i said, the function and the ajax call work, it just won't work with the serialized() post data – JimQ Oct 19 '13 at 23:26
  • The error message says that process_request() is not defined. Where is that function from? – kaiser Oct 19 '13 at 23:51
  • This function is in my plugin file. – JimQ Oct 20 '13 at 0:05
  • Alright, the referer in the string that is created for 'data2' seems to be the problem. If i replace the serialized() part with the string i got from firebug and take the referer out, all of a sudden it works. if i leave it in, same problem as described. So the new question is: Why is the referer in the string making wordpress throw that error message and how can i prevent it from being included with serialize()? It's not even part of the form, so where does it come from? – JimQ Oct 20 '13 at 12:53
3

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.

0

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.

  • You were right about the jQuery variable though, but it didn't change anything, as i said, if not serialized the whole thing does work like a charm. – JimQ Oct 20 '13 at 0:14
  • sry, this was the first comment, couldn't edit anymore: – JimQ Oct 20 '13 at 0:21
  • Thanks for the suggestion, but if i do that, the serialized() data will be defined as the value of add_my_data. Like this: add_my_data:action=process_request&add_my_data=whatever&... – JimQ Oct 20 '13 at 0:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.