PHP is famous for displaying ugly error messages, though they are useful at times. I know I can hide error messages with
error_reporting(0);
That's fine, but it leaves the user completely in the dark as to what is going on. The page has stopped working and they don't know why. How can I display a simple message along the lines of "Sorry, there is an error. Please send an e-mail to the webmaster"?
It would be the same message for all errors, and I'm thinking of maybe popping up a javascript alert, but open to any other ideas.
Implement an error and exception handler
You need to write a custom error handler like this. As you can see at the bottom, I am introducing a FATAL error. Here PHP does not spit any ugly error messages as you have quoted. It would just print Some Error Occured. Please Try Later.
<?php
set_error_handler( "log_error" );
set_exception_handler( "log_exception" );
function log_error( $num, $str, $file, $line, $context = null )
{
log_exception( new ErrorException( $str, 0, $num, $file, $line ) );
}
function log_exception( Exception $e )
{
http_response_code(500);
log_error($e);
echo "Some Error Occured. Please Try Later.";
exit();
}
error_reporting(E_ALL);
require_once("texsss.php");// I am doing a FATAL Error here
There are some rules that should apply to production servers:
Never show them the original PHP error message! Set display_errors = off.
Log those errors. Set log_errors = on and define a valid log target in error_log.
Monitor the error log, and act upon it. :)
The handling of errors to the user side has been sufficiently answered by the others.
You can write custom error handler that does it
http://php.net/manual/en/function.set-error-handler.php
This is typically done via Exceptions. If something goes awry, you'd throw an Exception and then "handle it" with an exception handler.
function exception_handler($exception) {
echo "Oops! Something went wrong! We're looking into it!";
}
set_exception_handler('exception_handler');
throw new Exception('Uncaught Exception');
You can also catch a number of fatal errors by using register_shutdown_function.
set_error_handler might also tickle your fancy.
User custom error handling set_error_handler
and exception handler set_exception_handler
and there you can do what ever you like.
Related
PHP is famous for displaying ugly error messages, though they are useful at times. I know I can hide error messages with
error_reporting(0);
That's fine, but it leaves the user completely in the dark as to what is going on. The page has stopped working and they don't know why. How can I display a simple message along the lines of "Sorry, there is an error. Please send an e-mail to the webmaster"?
It would be the same message for all errors, and I'm thinking of maybe popping up a javascript alert, but open to any other ideas.
Implement an error and exception handler
You need to write a custom error handler like this. As you can see at the bottom, I am introducing a FATAL error. Here PHP does not spit any ugly error messages as you have quoted. It would just print Some Error Occured. Please Try Later.
<?php
set_error_handler( "log_error" );
set_exception_handler( "log_exception" );
function log_error( $num, $str, $file, $line, $context = null )
{
log_exception( new ErrorException( $str, 0, $num, $file, $line ) );
}
function log_exception( Exception $e )
{
http_response_code(500);
log_error($e);
echo "Some Error Occured. Please Try Later.";
exit();
}
error_reporting(E_ALL);
require_once("texsss.php");// I am doing a FATAL Error here
There are some rules that should apply to production servers:
Never show them the original PHP error message! Set display_errors = off.
Log those errors. Set log_errors = on and define a valid log target in error_log.
Monitor the error log, and act upon it. :)
The handling of errors to the user side has been sufficiently answered by the others.
You can write custom error handler that does it
http://php.net/manual/en/function.set-error-handler.php
This is typically done via Exceptions. If something goes awry, you'd throw an Exception and then "handle it" with an exception handler.
function exception_handler($exception) {
echo "Oops! Something went wrong! We're looking into it!";
}
set_exception_handler('exception_handler');
throw new Exception('Uncaught Exception');
You can also catch a number of fatal errors by using register_shutdown_function.
set_error_handler might also tickle your fancy.
User custom error handling set_error_handler
and exception handler set_exception_handler
and there you can do what ever you like.
I have this code here to create error log:
error_log(date("[Y-m-d H:i:s]:")." You messed up!", 3, "../my-errors.log");
Here, we can see the custom error 'You messed up!' that I have set to print in the error log. I don't want to use the custom error here. Instead of this I want to set the Errors/Warnings/Notices that are generated by PHP itself.
Is this possible and how can we do that?
Thankyou
if I understood it well, you're looking for error_get_last():
array error_get_last ( void )
error_get_last — Get the last occurred error. / Gets information about the last error that occurred.
Take a look:
$last_error = error_get_last();
$formated_last_error = sprintf('%s in %s on line %d'.PHP_EOL,
$last_error['message'], $last_error['file'], $last_error['line']);
error_log(date(DATE_ATOM) . $formated_last_error().PHP_EOL, 3, '/tmp/logs.log');
However, you should take a look at set_error_handler() function which is a general approach.
i call an php pgm per cronjob at different times.
the pgm includes many php-files.
each file sends or gets data from partners.
How can i handle errors in one includes pgm.
at the time, one ftp-connection in an included pgm fails so the complete script crushes.
how can i handle this ?
You should wrap code, which is possible to crash, into try/catch construction. This will throw exeption, but the script will continue to work. More here.
Need to know more about you code inorder to give you definite answer.
In general php errors isn't catchable unless you define your own error handler from which you throw exceptions your self. Using the code below makes most runtime errors catchable (as long as they arent considered fatal)
error_reporing(E_ALL);
set_error_handler(function($errno, $errstr, $errfile, $errline) {
if($errno == E_STRICT || $errno == E_DEPRECATED) {
return true;
}
throw new RuntimeException('Triggered error (code '.$errno.') with message "'.$errstr.'"');
});
Btw, You could also define your own exception handler to display triggered errors with a full stack trace when an exception isn't catched.
Notice! I would not suggest that you add this code to a production website without rigorous testing first, making sure everything still works as expected.
Edit:
I have no idea what your code looks like, but I guess you can do something like:
require 'error-handler.php'; // where you have your error handler (the code seen above)
$files_to_include = array(
'some-file.php',
'some-other-file.php',
...
);
foreach($files_to_include as $file) {
try {
include $file;
}
catch(Exception $e) {
echo "$file failed\nMessage: ".$e->getMessage()."\nTrace:\n".$e->getTraceAsString();
}
}
I use a custom error handler with complete error reporting in PHP for tracking errors. This works great for debugging and logs all my errors in a database to investigate later.
Anyway, this method now disables the usage of # to ignore an error when one occurs. I now have the issue where I try to rename a directory on my system, because it may occasionally throw an error (if files are being accessed within it).
I would like to be able to catch this error in my code, to prevent executing the rest of the function, but I also do not want this error to appear in my error logging database (considering this error is 'managed' within the code, there is no need to see that it failed).
Is there a simple solution to this? I try using try / catch but it still appears to throw the error.
You can convert all errors/warnings/notices to exceptions
function exceptions_error_handler($severity, $message, $filename, $lineno) {
if (error_reporting() == 0) {
return;
}
if (error_reporting() & $severity) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
}
set_error_handler('exceptions_error_handler');
I think it is better to handle exceptions, than php native errors.
#zerkms' solution would work fine, but my error handler is already completed so to extend this to give me the functionality, I have simply included:
if ( error_reporting() == 0 )
return;
at the start of my handler. This way, if the # is used on a function, the error is still thrown, but ignored at the start of the handler (hence, not logged into the database, etc) and I will still get the boolean result from a function, such as rename().
This also still enabled me to use a try/catch solution on code if need be.
PHP fatal errors come back as status code 200 to the HTTP client. How can I make it return a status code 500 (Internal server error)?
header("HTTP/1.1 500 Internal Server Error");
This is exactly the problem I had yesterday and I found solution as follows:
1) first of all, you need to catch PHP fatal errors, which is error type E_ERROR. when this error occurs, script will be stored the error and terminate execution. you can get the stored error by calling function error_get_last().
2) before script terminated, a callback function register_shutdown_function() will always be called. so you need to register a error handler by this function to do what you want, in this case, return header 500 and a customized internal error page (optional).
function my_error_handler()
{
$last_error = error_get_last();
if ($last_error && $last_error['type']==E_ERROR)
{
header("HTTP/1.1 500 Internal Server Error");
echo '...';//html for 500 page
}
}
register_shutdown_function('my_error_handler');
Note: if you want to catch custom error type, which start with E_USER*, you can use function set_error_handler() to register error handler and trigger error by function trigger_error, however, this error handler can not handle E_ERROR error type. see explanation on php.net about error handler
Standard PHP configuration does return 500 when error occurs! Just make sure that your display_errors = off. You can simulate it with:
ini_set('display_errors', 0);
noFunction();
On production display_errors directive is off by default.
I have used "set_exception_handler" to handle uncaught exceptions.
function handleException($ex) {
error_log("Uncaught exception class=" . get_class($ex) . " message=" . $ex->getMessage() . " line=" . $ex->getLine());
ob_end_clean(); # try to purge content sent so far
header('HTTP/1.1 500 Internal Server Error');
echo 'Internal error';
}
set_exception_handler('handleException');
Since PHP >= 5.4
http_response_code(500);
echo json_encode( [ 'success' => false , 'message' => 'Crazy thing just happened!' ]);
exit();
Please set the httpCode before echo.
It is not possible to handle PHP E_ERROR in any way according to the PHP documentation:
http://www.php.net/manual/en/function.set-error-handler.php
Nor is is possible to handle "E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT" according to that link.
You CAN provide a handler for the other error, warning, and notices including E_USER_ERROR, but that's really not as useful as it sounds since this error only gets thrown intentionally by the programmer with trigger_error().
And of course you can catch any Exception (even the ones thrown by the native PHP functions).
I agree that this is a problem. Servers should NOT return 200 OK when application code crashes and burns.
You can use php error handling
http://www.w3schools.com/php/php_error.asp
You would have to catch the thrown error using try/catch and then use that catch block to send a header() with the 500 error.
try {
...badcode...
throw new Exception('error');
} catch (Exception $e) {
header("Status: 500 Server Error");
var_dump($e->getMessage());
}
If the fatal exception is not surrounded by try {} catch blocks then you must register a global handler and use register_shutdown_function() to check for an error at script end.
Never forget to set header("HTTP/1.1 200 OK", true, 200); as the last line of any execution path:
//first things first:
header("HTTP/1.1 500 Internal Server Error", true, 500);
//Application code, includes, requires, etc. [...]
//somewhere something happens
//die();
throw new Exception("Uncaught exception!");
//last things last, only reached if code execution was not stopped by uncaught exception or some fatal error
header("HTTP/1.1 200 OK", true, 200);
In PHP 5.4 you can replace the header function above with the much better http_response_code(200) or http_response_code(500).
The hard thing when dealing with fatal errors (compile errors, for example a missing semicolon) is that the script won't be executed, so it won't help to set the status code in that script. However, when you include or require a script, the calling script will be executed, regardless of errors in the included script. With this, I come to this solution:
rock-solid-script.php:
// minimize changes to this script to keep it rock-solid
http_response_code(500); // PHP >= 5.4
require_once("script-i-want-to-guard-for-errors.php");
script-i-want-to-guard-for-errors.php:
// do all the processsing
// don't produce any output
// you might want to use output buffering
http_response_code(200); // PHP >= 5.4
// here you can produce the output
Direct your call to the rock-solid-script.php and you're ready to go.
I would have liked it better to set the default status code to 500 in .htaccess. That seems more elegant to me but I can't find a way to pull it off. I tried the RewriteRule R-flag, but this prevents execution of php altogether, so that's no use.