jquery + php: catching php error from ajax - php

i am using jquery's $.post and the server script sometimes will raise a php error.
any ideas how i could catch that error and report it back to the client script?
i have tried set_error_handler() but unfortunately for some reason it doesn't work on fatal php errors, so when there's an error simply nothing will happen. thanks

The best way to do this is to have the script always return json and have a success:true/false in it, then you will never need the error handler.
I know you can't always do that so according to the docs you can do this found here:
var jqxhr = $.post("example.php", function() {
alert("success");
})
.success(function() { alert("second success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
// perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function(){ alert("second complete"); });
Update
With xml:
<root>
<success>true/false</success>
<response>
<response_node_1>Foo</response_node_1>
<response_node_2>Bar</response_node_2>
</response>
</root>

You can't track fatal errors from within the same PHP script. As you write set_error_handler is not working on those. There is not much you can do about it but look for the HTTP response code (500 - Internal Server Error).
What you can do is to make your code more failsafe/devensive/robust so fatal errors don't appear. Do this by analysing your php error log which fatal errors appear and look inside the related code why they appear and how you can prevent these with correct error checking.

You can set up global error handling by using something like
$.ajaxSetup({
error:function(x,e){
if(x.status==0){
alert('You are offline!!\n Please Check Your Network.');
}else if(x.status==404){
alert('Requested URL not found.');
}else if(x.status==500){
alert('Internel Server Error.');
}else if(e=='parsererror'){
alert('Error.\nParsing JSON Request failed.');
}else if(e=='timeout'){
alert('Request Time out.');
}else {
alert('Unknow Error.\n'+x.responseText);
}
}
});
Or in the json response look at the error handler and decide what to do when it is passed with certain variables.

You don't want scripts to output error information in production environments, so you should disable error reporting there.
What kind of errors are you talking about? In your development environment, enable all errors and track them down, and program defensively to prevent errors from happening. There are many ways of doing this, depending on where the error comes from.
Finally, if you can trap errors, you could set some kind of error flag ($error = true), and on the final output, perform something like this:
echo '{"success": $error}';
if (!$error)
{
echo $the_requested_data;
}
You can then let jQuery read the success variable.

Depending on php configuration fatal errors will sometime (thanks PHP) result in an HTTP 200 response that will not be catched by jQuery as error but will be rather seen as a good response. So, as someone was already pointing, you should avoid having fatal errors (double checking error-prone parts of your code, catching exceptions, checking array indexes, declaring variables before using and so on).

i found my solution:
as i'm expecting a xml to be returned - i only need to check for the content-type of the response, when php raises an error i'm getting text/html instead of text/xml :)

Related

Capture PHP error body within jQuery AJAX

I have an AJAX build that functions like a CMD line box. It allows me to breakup and scrub 100,000+ line CSV files on servers where MySQL 'IMPORT from FILE' is disabled. That "scrub" process is different for every client. Therefore I have built this tool to allow me to include various PHP scripts
It works great except for error handling in 1 area: the PHP error level.
I want to log the error using JS, specifically console.log()
consider then the following JS
$.ajax({
type: 'POST',
dataType: 'text', //also tried json
url: PHP_SCRIPT, //for sake of referance
data: $.param(data), // param object values as POST values
cache: false,
error: function(error) {
console.log("fubar:" + JSON.stringify(error));
If I cause an error in PHP_SCRIPT (that is not handled using try/catch and output as JSON) then I get the following "ambiguous" reply
stringify:{"readyState":4,"responseText":"","status":500,"statusText":"error"}
Here is the problem: responseText is empty.
What is really happening in PHP_SCRIPT is this error:
Fatal error: Uncaught UnexpectedValueException: RecursiveDirectoryIterator::
Which I can of course see if I run the PHP script (and I know why its happening, my question is not about the RDI error). Consider it could be other errors as well: a failed include, a mistake in code, ect. But JS and jQuery AJAX do not seem to "capture" the body of the failed PHP script.
GOAL: I want to "capture" PHP errors and show them using console.log() (or even my makeshift CMD line box) so I do not have to cut up the PHP_SCRIPT's and debug each line separately. I do not understand why error.responseText does not capture the output.
Ideally - the PHP "Fatal error" above should have been captured as TEXT and output in the log.
Note: I have PDO try/catch handling for the DB queries where I can output a success.error object and handle it appropriately, catching the PDO exception and log it to the console. Alas, I see no useful way to handle other PHP errors (such as a failed include or other common PHP mistakes). If it matters- I am using WordPress Admin AJAX with nonce and die() and my scripts work great, but during dev of new scripts catching errors is annoying.
Question Summary:
Is there a way to catch all/any PHP errors that are not output as JSON and console.log them when $.ajax - error happens?
Is there some way to capture the 'body' of the PHP error and console.log it?
Thank you for your consideration in this matter
UPDATE---
Added video to clarify: http://www.screencast.com/t/ZyCeaMyAxBO
Something like this will capture all uncaught exceptions and output a message in JSON format.
set_exception_handler(function($e) {
$msg = "Error: ";
// maybe you want to treat some differently?
if ($e instanceof \PDOException) {
$msg = "Database error: ";
}
// you can access all properties of the exception to build a reply
$msg .= $e->getMessage();
header("Content-Type: text/json");
echo json_encode(["message" => $msg]);
});
You can't catch ALL error situations, basically because you'll have to write the error handler in PHP and some errors (like parse errors) cause that the script doesn't even compile and therefor cannot be executed at all.
But with set_error_handler() / set_exeception_handler() you can probably cover a good portion...

Send PHP errors through JSON

I am trying to debug a page that sends emails with attachments via ajax and when PHP kicks out an error, I get "Parse Error" because the error is not being sent back via JSON. Is there anyway to wrap up the PHP errors so I can alert them and see exactly what PHP errors are coming up?
What I am hoping to see in the js alert is the same thing you would see printed on the screen if this form was not submitted using ajax.
Use HTTP status codes. Simple and clean.
On the client side: You can handle the HTTP states with the success and failure callbacks of the common JavaScript frameworks.
On the server side: Use exceptions and handle them with a catch block. In the catch block set the HTTP status code and echo the exception message. Or use the less fancy set_error_handler() function and set the status code and error message in the callback function.
Fatal errors usually can't be handled *.
Try improving your code and just don't make parse errors or other fatal errors. Handling warnings and notices is easy: http://php.net/manual/en/function.set-error-handler.php
*: It's possible but it takes a lot of effort.
function json_error($msg) {
header('HTTP/1.1 500 ' . $msg);
die(json_encode(array('error' => $msg)));
}
json_error('something bad happened');
This will trigger the error: ajax callback on the JS side.
echo json_encode(array('anything' => 'really', 'any key' => 'any value'));
Will trigger the success: callback.
You'd use exception-handling, look here: http://www.php.net/manual/en/language.exceptions.php

jQuery AJAX error handling

I've searched the questions on here, but I don't have a good understanding of how to use the error handling in jQuery's AJAX (im a noob, so it just really doesn't make sense.)
Can anybody describe this to a beginner? I'm currently posting information to a PHP script via AJAX, but want to allow jQuery to recognize if the returned data from the script is an error or success.
Thanks!
Dave
The error return from the ajax call is returning the results from a page load that was not successful. It may be that your php page returns a valid page, but with results that are not what you want. This is handled withing the success return. Hopefully the following code snippit will help illustrate...
$.ajax({
type: "POST",
url: "login.php",
data: "action=login&user=" + user + "&pass=" + pass,
success: function(xhr){
if ((xhr == "Invalid Login")
|| (xhr == "Invalid charaters in username.")
|| (xhr == "Missing username or password.")
|| (xhr == "Unknown Error")) {
$("#loginMessageContent").html(xhr);
}
else {
simplemodalClose (dialog);
}
},
error: function(xhr) {
alert ("Oopsie: " + xhr.statusText);
}
});
The jQuery AJAX error handling is implemented to handle if the HTTP Request has an error not if your script is returning "error" or "success". If the server throws an error (404 Not Found or 500 Server Error as an example) then it will trigger the error functions of jQuery. It can be handled a few ways, but one nice way is to show a div letting the user know there was an error.
HTML
<div id="error" style="display: none">There was an error processing your last request</div>
jQuery
$(function(){
$("#error").ajaxError(function(){
var $error = $(this);
$error.slideDown(500, function(){
window.setTimeout(function(){
$error.slideUp(500);
}, 2000);
});
});
});
If an error occurs, none of your "success" methods will fire, and that div will slide down, wait 2 seconds, then slide back up.
Testing your script for errors
As I mentioned what you described sounds like your server script is sending "error" or "success" or something similar back to the client.
If you are using a $.post, for example, your error handling code might look like this:
$.post('/your/url', { save_me: true }, function( data ){
if(data == "error"){
// handle error
} else {
// handle success
}
}
This is only 1 approach. I am building an application that returns all of its data in JSON. If there is an error then the JSON message is changed to reflect this. Every return object has a "status" of
either "success" or "error". If it is an error then there is an "error_message" part of the JSON that
describes the error.
I hope that helps.
Even though it's not your problem, I'll post here since it's related.
With the recent JQuery v1.4 release, JSON responses are now validated. It broke my app because I returned:
{success:true}
and now it's required to be
{"success":true} // HAS to be double quotes, single won't do it
If incorrect, it calls the error handler. Easy fix but took a bit to figure out.

Has anyone ever successfully tracked down uncaught exception during ajax request?

How do ajax know whether it failed or succeeded if server side doesn't echo anything back?
$.ajax(error:..,success:..)
I met with this exception in my test:
uncaught exception: [Exception...
"Component returned failure code:
0x80040111 (NS_ERROR_NOT_AVAILABLE)
[nsIXMLHttpRequest.statusText]"
nsresult: "0x80040111
(NS_ERROR_NOT_AVAILABLE)" location:
"JS frame ::
http://localhost/script/tab.js ::
anonymous :: line 69" data: no]
The server side code is :
$id = process();
And for the purpose of testing,I have exit() in process();
Is that the reason for this exception?If so,why?
EDIT
I looked over to the line that cause exception,it's the error handling function of $.ajax()
error:function(XMLHttpRequest, textStatus, errorThrown){
alert(XMLHttpRequest.statusText);alert(textStatus);alert(errorThrown);
}
Anything wrong here?
The httprequest also returns a status such as 200 == ok, 404 == not found, 12152 == connection closed by server and so on..
Just read up on the status id's what they mean so you can look for them. you can also for debugging reasons just write out myhttprequest.status to the document and it shows what status it returned.
This depends on the status code the request returns. A successful request returns a status code in the range of 2xx, an error is in the range of 4xx of 5xx.
For more information see Wikipedia: List of HTTP status codes.
It would still get a response from the server, with the data part of it being empty. If it got no response at all, that would be an error.
http://docs.jquery.com/Ajax/jQuery.ajax#options
Give an option for success and error These functions will be called after the call is made.
There are four possible scenarios that you could get:
the server isn't there or refuses the connection (this is identifiable by the sockets library that the browser uses, which will report the connection failure)
the connection works and the server returns a non-success error code - this comes back in the header. Indeed, the request can succeed (200 code) even with an empty body, that's perfectly valid
the connection comes up but the server fails to respond - I'm not clear on the details of this, but i'd expect the JS to eventually time out because no response was received and return a failure based on that.
the connection comes up but the server responds incorrectly (e.g. no headers) - the JS implementation should return this as an error.
In any case, all the error scenarios are handled by the Javascript core's XMLHttpRequest implementation - jQuery just wraps it up with slightly tidier interface.
In your case (now you've provided more information) I would recommend that you use Firebug to see what the server response to your request is. That said, you shouldn't be getting an exception for anything inappropriate from the server, the JS should call the same error callback for all the above cases.
are you missing { } ?
$.ajax(error:..,success:..)
should be
$.ajax( { error: function( ){ } } );
if that's it, sorry dude, that would be annoying to have spent that much time on, haha
I fixed this by specifying a timeout in my ajax call. The ajax timeout was just giving up after X amount of time. Even though the page ended up returning data, the ajax object just gave up and bailed, but threw this error.

Complete AJAX feedback

I build JQuery/JS/PHP/mySQL app with DB records management and need to provide reliable & complete feedback to the user on AJAX calls, modifying back end DB records. The problem IMHO is $.ajax success: and error: functions indicate just AJAX transport layer success and not the whole process. What if DB modification fail? How can one provide the complete feedback to the user?
I ended up with
$.ajax({
url: "/action/delete",
data: "rowid="+rowid,
complete: function(xmlHttp) {
if ( xmlHttp.responseText ) alert('Success - back end returned "success"');
else alert('failure - back end returned NULL')
}
});
and PHP response:
$success = deleteRecord( $_GET(rowid) );
if($success) {
print 'success';
} else {
print NULL;
}
exit();
The idea is simple - if I manage to get positive feedback from the back end, then the whole operation succeeded, if not - user don't care where problem occurred.
Thank you in advance, your feedback is highly appreciated.
If you respond to the request with some json data instead of just some new html to insert into the DOM, you can place whatever kinds of error codes and messages you like with the data. For example, if your response was something like...
{
errorstate: 0,
errormsg: "All systems are go",
displaytext: "stuff I want to display when all goes well"
}
Your javascript code can examine this data and do whatever it feels it needs to. It also allows you to push more of the error handling into your server script which can often be simpler.
Try http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback
One possible solution would be to use the HTTP response code to signal a failure, like 200 OK, everything's ok, and 500 Internal Server Error on error, which you can simply check when you reach state 4.
In PHP I believe this is done through header("HTTP/1.0 200 Ok") before any other data is sent. If you're afraid data will be sent by mistake before you can evaluate the correct header to set you can turn on output buffering.
How you wish to present the data is of course up to you, you could for example on 500 just have document.getElementById("myerrorbox").innerHTML = xmlHttp.responseText, or similar, and render a partial html-document in your php-program.
I send status messages back to the client. Along with the error flag. And then my JavaScript code displays the message it got from the server, and colours the message according to the error flag.
I find that to be quite efficient.

Categories