Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax call to php script returns 404 error

I'm a WordPress designer, I developed a contact form for one of my themes that's validated via jQuery.

Please check the code below, then read the notes beneath.

$('.submitemail') .click(function() {

    //VALIDATION CODE GOES HERE

    if ( /*VALIDATED SUCCESSFULLY*/ ) {


        $.ajax({
            type: 'POST',
            url: templatePath+'/lib/scripts/sendEmail.php',
            data: 'visitorname=' + visitorname + '&visitoremail=' + visitoremail + '&visitormessage=' + visitormessage,

            success: function(contactResults) {
                //SUCCESS CODE
            }

        });
    }
});

Notes:

  • sendEmail.php is a correct script that sends email using PHPmailer class.
  • templatePath variable has the value of the full template path which looks like this: http://somedomain.com/wp-content/themes/themename
  • The jQuery code above is located in lib/scripts/jfunctions.js (same directory of the php script)
  • The whole process (ajax and php) works perfectly as expected in many servers, (tested in two servers by me and other servers by my theme users).

The Problem:

In SOME servers, the success handler is not triggered while the ajax call to sendEmail.php is actually passed successfully and the php script is processed and email is sent.

When I check with firebug to see why the success handler is not triggered, firebug shows "not found 404 error", It's like a false alarm.

Possible causes:

I think some servers is configured to block such ajax calls.

What might be the cause for this weird issue? How to fix it?

Thanks in advance.

@nowk: sendEmail.php code is:

<?php 
// Code for loading WordPress environment goes here //

$themeName_optionTree = get_option('option_tree');

$name = trim($_POST['visitorname']);
$email = $_POST['visitoremail'];
$message = $_POST['visitormessage'];


$site_owners_email = $themeName_optionTree['owner_email'];
$site_owners_name = $themeName_optionTree['owner_name'];
$email_subject = $themeName_optionTree['email_subject'];
$success_message = '<p class="success-box">' . $themeName_optionTree['success_message'] . '</p>';

if (strlen($name) < 2) {
    $error['name'] = 1; 
}

if (!preg_match('/^[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*+[a-z]{2}/is', $email)) {
    $error['email'] = 1;    
}

if (strlen($message) < 2) {
    $error['message'] = 1;
}

if (!$error) {

    require_once('PHPMailer_v5.1/class.phpmailer.php');

    $mail = new PHPMailer(true);

    try {
        $mail->From = $email;
        $mail->FromName = $name;
        $mail->Subject = $email_subject;
        $mail->AddAddress($site_owners_email, $site_owners_name);
        $mail->Body = $message;
        $mail->Send();
        echo $success_message;
    } catch (phpmailerException $e) {
        echo '<p class="warning-box">' . $e->errorMessage() . '</p>';
    } catch (Exception $e) {
        echo '<p class="warning-box">' . $e->getMessage() . '</p>';
    }
}
?>

Please note that the above code executes perfectly even when ajax returns 404, weird huh!.

like image 228
mobi Avatar asked Apr 22 '11 22:04

mobi


2 Answers

Since the server sends a 404 (for god knows what reason), there are two ways to fix/circumvent this:

  1. Ignore the HTTP response code and change success to complete in the jQuery ajax call, so that the handler is executed when the request is done no matter the server response. You know the server response (it always works). The HTML should still be available in the jQuery complete handler.
  2. Overwrite the 404 that something sends on the server (probably something Wordpress) by executing (before printing any output): header('HTTP/1.1 200 OK'). Since the script is executed, this will overwrite the crazy 404 and jQuery will receive that 200 and execute the success handler.

You could try both =) I'm pretty sure the first one will work (but that's not so clean). I'm also pretty sure the 2nd will work, but I don't know Wordpress well enough to make promises =)

like image 153
Rudie Avatar answered Sep 21 '22 12:09

Rudie


I'm guessing it's because Wordpress already has an AJAX mechanism built in and it stops you from implementing it on your own. This page explains how to add AJAX to plugins:

http://codex.wordpress.org/AJAX_in_Plugins

Here's a snippet from the page:


Ajax on the Administration Side

Since Ajax is already built into the core WordPress administration screens, adding more administration-side Ajax functionality to your plugin is fairly straightforward, and this section describes how to do it.

Here's a short example. All this will be in one file.

First, add some javascript that will trigger the AJAX request:

<?php
add_action('admin_print_scripts', 'my_action_javascript');

function my_action_javascript() {
?>
<script type="text/javascript" >
jQuery(document).ready(function($) {

    var data = {
        action: 'my_action',
        whatever: 1234
    };

    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
    $.post(ajaxurl, data, function(response) {
        alert('Got this from the server: ' + response);
    });
});
</script>
<?php
}

Then, set up a PHP function that will handle that request:

<?php 

    add_action('wp_ajax_my_action', 'my_action_callback');

    function my_action_callback() {
    global $wpdb; // this is how you get access to the database

    $whatever = intval( $_POST['whatever'] );

    $whatever += 10;

    echo $whatever;

    die(); // this is required to return a proper result
}

That's it! You will need to add a few details, such as error checking and verifying that the request came from the right place ( using check_ajax_referer() ), but hopefully the example above will be enough to get you started on your own administration-side Ajax plugin. NOTE: Since Version 2.8, The javascript global variable ajaxurl can be used in case you want to separate your javascript code from php files into javascript only files. This is true on the administration side only.

like image 20
Greg Tatum Avatar answered Sep 21 '22 12:09

Greg Tatum