42

Is there a way to get PHP to return an AJAX error code if the PHP script fails somewhere? I was following a tutorial and typed this in to my PHP:

$return['error'] = true;
$return['msg'] = "Could not connect to DB";

And all was well, until I realised it was JSON data. Is there a way to return errors using standard $_POST and returned HTML data (as in, trigger jQuery's AJAX error: event?

Bojangles
  • 99,427
  • 50
  • 170
  • 208

4 Answers4

107

I don't know about jQuery, but if it distinguishes between successful and unsuccessful (HTTP 200 OK vs. HTTP != 200) Ajax requests, you might want your PHP script respond with an HTTP code not equal to 200:

if ($everything_is_ok)
    {
        header('Content-Type: application/json');
        print json_encode($result);
    }
else
    {
        header('HTTP/1.1 500 Internal Server Booboo');
        header('Content-Type: application/json; charset=UTF-8');
        die(json_encode(array('message' => 'ERROR', 'code' => 1337)));
    }
Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • 29
    Thank you :-) looks simple! Also, is `Booboo` official, or can it be anything? – Bojangles Dec 12 '10 at 10:04
  • 10
    Hehe. It can be anything. The "official" term is "Internal Server Error", though. – Linus Kleen Dec 12 '10 at 13:35
  • 10
    @Bojangles comment of the century lol ^_^ Could not prevent myself from commenting. :p – Gogol Nov 28 '14 at 09:30
  • 4
    @LinusKleen No, I'm thinking `Booboo` should be the standard. Either that or `Foofd` – Kellen Stuart Sep 06 '16 at 14:20
  • 1
    Just be aware that this could lead to trouble on standard IIS installation/configuration, as IIS delivers a htm site and kind of overwrites your json repsonse, and your client side JSON.parse() which you may have implemented, throws an exception. Altering the web.config with the following line helped me but I am not sure whether that's the case for all IIS config combinations: `` – John Archer Apr 05 '17 at 13:32
1
$return = array();
$return['msg'] = "Could not connect to DB";

if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']  == 'XMLHttpRequest')
{
    header('Cache-Control: no-cache, must-revalidate');
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
    header('Content-type: application/json');
    die(json_encode($return));
}
Webist
  • 39
  • 1
  • 9
  • You need to force your requests with $_SERVER['HTTP_X_REQUESTED_WITH']. browsers like Firefox wont evaluate the response when the Accept header does not match. – Webist Dec 12 '10 at 10:19
-1

try this out. Hope it helps.

<!-- This is index.php --->
<html>
        <head>
            <script src="js/jquery.js" type="text/javascript"></script><!-- link to jQuery -->
            <script language="javascript"> 
            $(document).ready(function () {
                $('input#send').click(function(){
                    /* Empty div#error and div#result incase they contain info from the last submission */
                    $('#error').empty('');
                    $('#result').empty('');
                    /* Client-side validation */
                    var name = $("input#name").val();
                    var age = $("input#age").val();
                    if (name==''){
                        alert('Insert your name.');
                    }
                    else if (age==''){
                        alert('Insert your age.');
                    } else { 
                        var params = 'name=' + name + '&age=' + age;   
                        $.ajax({        
                             url:'b.php',        
                             type:'post',                 
                             dataType:'html',            
                             data:params,
                             cache: false,            
                             success:data     
                             }); 
                        function data (html) {
                            var $html = $( html ); // create DOM elements in a jQuery object
                            /* Return errors from 'b.php' */
                            $html.filter('#err').appendTo("#error");
                            /* Return valid Post */
                            $html.filter('#res').appendTo("#result");
                            /* Clear name input */
                            $('input#name').val('');
                            /* Clear age input */
                            $('input#age').val('');
                        }
                    }
                }); 
            }); 
            </script>
            <style type='text/css'>
                #error{
                    color:maroon;
                    font-weight:bold;
                }
                #result{
                    color:green;
                    font-weight:bold;
                }
            </style>
        </head>
        <body>
            <div id="error"></div><!-- View Errors -->
            <div id="result"></div><!-- View valid Post -->
            <input type='text' name='name' id="name" value='' /><br/ >
            <input type='text' name='age' id="age" value='' /><br/ >
            <input type='submit' name='send' id="send" value='Send' />
        </body>

<?php
/* This is b.php */
if(($_POST['name']=='')||($_POST['age']=='')){
    $error = '<div id="err">Error: Fill in ALL fields.</div>';
} elseif(is_numeric($_POST['name'])){
    $error = '<div id="err">Error: Name should NOT contain numbers.</div>';
} elseif(!is_numeric($_POST['age'])){
    $error = '<div id="err">Error: Age should ONLY contain numbers.</div>';
} else{
    $result = '<div id="res">Hi '.$_POST['name'].', you are '.$_POST['age'].' years old.</div>';
}
echo $error;
echo $result;
?>
Tangi
  • 33
  • 2
-2

For simple transfer of data from PHP to AJAX, Json encoding or key value pairs are not always necessary. It can be simply done using string handling.

A sample code explaining this functionality is below.


    $query = "SELECT email FROM login WHERE email = '". mysqli_real_escape_string($conn,$email) ."' AND password = '". mysqli_real_escape_string($conn,$pass) ."'" ;

    $result = mysqli_query($conn,$query);
    $row=mysqli_fetch_row($result);

    $row_cnt = mysqli_num_rows($result);
    $s_email = $row[0];

    if ($row_cnt == 1) {
        $response="success";
    } else {
    $response = "Invalid Credentials";
    }

    $conn->close();

    $_SESSION["email"]= $s_email;
    echo $response;

This code shows how a 'success' response is sent back to ajax calling the php code. Further in ajax the following could be done to retrieve the response.


    $.ajax({ type : 'POST',
          data : {email: $('#email').val(), password: $('#pass').val()},
          url  : 'login.php',              
          success: function (data) {
            if(data == 'success'){  //the value echoed from php can be stored in the data variable of ajax
                window.location.assign('upload.php');
            }
            else{
                alert(data);
            }
          },
          error: function ( xhr ) {
            alert("error");
        }
    });

The above concept can be extended to return MULTIPLE VALUES also. This method allows simple tranfer of data from PHP to AJAX in a string format.

We have to follow a simple step of echoing everything we need to send as a response from the php to ajax, seperated by a unique seperator.


    echo $response.#;
    echo $email.#;
    echo $password.#;
    echo "Hello".#;
    echo "World";

Then the variable data in ajax could be simply retrieved as in the above example and a simple function like,


    var res = data.split("#");

data, being the variable within ajax. The res array can then be used within js for whatever purpose we need.

  • This doesn't answer my original question. I didn't want to roll my own data format (which is a really bad idea), I actually wanted to send a 500 in the status header. As an aside, what's wrong with JSON? `Seeing such complicated answers pains me.`; your answer is probably the most unnecessarily complex by creating your own data format. You should also be using [PDO](http://php.net/manual/en/book.pdo.php) (or better alternative; I haven't been keeping up with the PHP ecosystem) instead of `mysqli_*` for better security. – Bojangles May 30 '17 at 11:12
  • Sorry if the statement appeared offensive to other answers. I just proposed a simple idea to return data instead of json encoding. Having control of data sometimes is of great help instead of relying on built in functionalities. And I've used mysqli just for an example PDO is by far one of the best methods. – Binayak Banerjee May 31 '17 at 14:44