I'm trying to catch error when invalid data to imagecreatefromjpeg are passed. Cake php displays error page saying Fatal Error Cake\Error\FatalErrorException so this code supposed to work but it is not:
try {
$src_img = imagecreatefromjpeg($image);
} catch (\Cake\Error\FatalErrorException $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
I'm also tried to use \Exception, \Cake\Core\Exception\Exception, \ErrorException but with no success.
imagecreatefromjpeg() normally shouldn't cause fatal errors, but only warnings, you may want to investigate that further.
Anyhow, catching fatal errors via try...catch is only possible as of PHP 7, where most of them have been changed to exceptions. You'd have to catch \Error or \Throwable in that case. However there are still fatal errors that cannot be catched, for example when require() fails, or memory is exceeded.
\Cake\Error\FatalErrorException is being created internally in a regular error handler, where (uncatched) fatal errors will be handled, ie that exception is not being thrown, and therefore cannot be catched.
See also
PHP Manual > Language Reference > Errors > Errors in PHP 7
PHP Manual > Language Reference > Predefined Exceptions > Error
PHP Manual > Language Reference > Predefined Interfaces and Classes > Throwable
CakePHP Source > \Cake\Error\BaseErrorHandler::handleFatalError()
Related
EDIT: It turned out that what I stated in this question was totally wrong. The code was actually turning off error reporting explicitly prior to autoloading, in places where I hadn't found it.
So this question is basically useless. The accepted answer is correct.
In my current configuration, whenever some PHP file has fatal errors such as syntax errors or calling a function that does not exist, I usually get an error message such like:
Parse error: syntax error, unexpected <whatever> in /path/to/file.php on line XXX
or
Fatal error: Call to undefined function whatever() in /path/to/file.php on line YYY
or the like in the very output.
However, I am using third-party libraries which use a third-party autoloader. Whenever there's a fatal error in any of the autoloaded classes (including parse errors or calling unexisting functions - actually not completely sure about the latter but definitely of the parse error case), I just get a blank page, and not only that: no error is even logged in Apache's error_log file, where usually PHP fatal errors would be logged. So debugging becomes impossible.
I can't stress this enough: this only happens when the fatal error is in some autoloaded file. In every other case (including of course errors in files included via require(), include() and the like), the same errors do show up in the output and in the error_log.
I didn't write the autoloader code, but it's basically like this:
// no idea why this line, but I don't think it's relevant:
ini_set('unserialize_callback_func', 'spl_autoload_call');
spl_autoload_register(array('My_Autoloader', 'autoload'), true);
class My_Autoloader {
static function autoload($classname) {
$filename = //.... computes $filename from $classname
require_once($filename);
}
}
There must be a way to have the autoloader throw errors the same way they would be thrown (and handled) if the errors were not in an autoloaded file, right?
How do I get that?
The only way that the code would behave as you suggest is if the third party code is overriding the error reporting. (EDIT by OP: Yep, it turns out it actually was.) That is usually considered good practice for production systems, but it should be logging the error.
That your third party code is causing such errors gives me pause to wonder about its quality, but we'll ignore that for now.
PHP's built in mechanisms will handle the reporting (to the browser) and the logging (to file). Non fatal errors can be managed by your own code after calling set_error_handler() however fatal errors are not handed off via this route. It is possible to trap and handle fatal errors in your own code using register_shutdown_function(). But start by checking your log files.
If, as you say, both error logging and error reporting are disabled, then stop using this third party code - it is toxic.
Syntax Error Check only on Command Line
With php -l somefile.php from PHP
shell_exec('php -l /fullpath/to/somefile.php')
but you have to analyse the respone string for errors.
Normal response No syntax errors detected in somefile.php
In PHP <= 5.0.4 there was php.net/manual/en/function.php-check-syntax.php
Here a fatal error catch that works:
register_shutdown_function(function(){
$err=error_get_last();
if($err['type']===1){
/*you got an fatal error do something, write it to an file*/
#file_put_contents(var_export($err,true),'myfatalerror.log');
}
});
Hope that helps:)
Use php exception so you can call your file into
function inverse($x) {
if (!$x) {
throw new Exception('Division par zéro.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Exception reçue : ', $e->getMessage(), "\n";
}
I am experiencing an Exception due to a recursive function in my code, due to the nature of what I am coding, the exception can just be ignored and FALSE returned instead. So here is som simplified code to illustrate my issue.
function recursive() {
try{ recursive(); }
catch(Exception $e)
{ echo "Error Caught!"; }
}
recursive();
I can't seem to catch the 'Maximum function nesting level of '100' reached, aborting!' exception.
Have I misunderstood how try-catch's work?
Because it is a Fatal Error and not an Exception so you can not use try & catch.
An Error in general means that the execution of the program by all means can not be continued and has to be aborded.
An Exception on the other hand is like a warning, meaning something has gone wrong, but with the right handling of this exception the program execution can continue.
An Example for try & catch could be:
try to connect to the database ... function connect throws an exception because database server is not reachable ... you catch the exception and decide, well then lets read the stuff from a cached file. The intention behind exception is, to let the developer decide wether he wants to catch the exception and continue the program execution or suspend it.
"PHP Fatal error: Maximum function nesting level of '100' reached, aborting!"
It is a "Fatal error", not an exception. There is no way in PHP to convert it to Exception using set_error_handler (which is good for converting lower level errors to exceptions).
In case of "Fatal error" the only thing You can do is to make some cleanup using register_shutdown_function where you can call error_get_last and recognize that this particular fatal error occured. But thats all You can do, there is no way to continue designed program flow.
BTW this partical fatal error can happen only when You have XDebug module enabled in Your php.ini.
The entry point (front controller) for our software is wrapped in a try catch block which catches exceptions and then includes a PHP file to show a friendly error page, as well as emailing us about the exception. This work perfectly, however it misses PHP fatal errors which just show a HTTP 500 response. I'm trying to catch those errors in the same way as exceptions.
At the moment, we have this in the application's entry point:
try {
// Register a shutdown handler for fatal errors
register_shutdown_function(function() {
$error = error_get_last();
// Did this request throw an error that wasn't handled?
if ($error !== null) {
throw new Exception('PHP fatal error!');
}
});
// ...normal front controller stuff
} catch (Exception $e) {
// show fancy error screen with debug information
include 'themes/error/500.php';
}
Here, I'm throwing an exception when PHP throws a fatal error in the hopes that it gets handled by the normal exception handling procedure. However, the exception never gets caught:
Fatal error: Uncaught exception 'Exception' with message 'PHP fatal error!'
How can I achieve what I want to do here?
You should not use register_shutdown_function() for that - it makes no sense since you're already at stage when script is exiting. PHP allow you to handle errors via set_error_handler() function.
But note, you can not handle fatal errors with that (such as calling undefined functions) - and, of cause, parse error as well:
The following error types cannot be handled with a user defined
function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the
file where set_error_handler() is called.
I'm playing around with exceptions in PHP. For example, I have a script that reads a $_GET request and loads a file; If the file doesn't exists, an new exception should be thrown:
if ( file_exists( $_SERVER['DOCUMENT_ROOT'] .'/'.$_GET['image'] ) ) {
// Something real amazing happens here.
}
else {
throw new Exception("The requested file does not exists.");
}
The problem is that, when I try to supply an non existent file for the test, I got a 500 error instead of the exception message. The server log is the following:
[09-Jul-2013 18:26:16 UTC] PHP Fatal error: Uncaught exception 'Exception' with message 'The requested file does not exists.' in C:\sites\wonderfulproject\script.php:40
Stack trace:
#0 {main}
thrown in C:\sites\wonderfulproject\script.php on line 40
I wonder if I'm missing something real obvious here.
I've checked this question PHP fatal error: Uncaught exception 'Exception' with message but it's not quite like my issue, and have no concise answer.
Help, please?
* EDIT *
It seems this is something related to the throw keyword. If I use echo for example, I got the message printed on the screen, like this:
exception 'Exception' with message 'The file does not exists.' in C:\sites\wonderfulproject\script.php:183 Stack trace: #0 {main}
Why is that?
** EDIT 2 **
Thanks to #Orangepill, I got a better understanding about how to handle exceptions. And I found a superb tut from nettuts that helped a lot. The link: http://net.tutsplus.com/tutorials/php/the-ins-and-outs-of-php-exceptions/
This is expected behavior for an uncaught exception with display_errors off.
Your options here are to turn on display_errors via php or in the ini file or catch and output the exception.
ini_set("display_errors", 1);
or
try{
// code that may throw an exception
} catch(Exception $e){
echo $e->getMessage();
}
If you are throwing exceptions, the intention is that somewhere further down the line something will catch and deal with it. If not it is a server error (500).
Another option for you would be to use set_exception_handler to set a default error handler for your script.
function default_exception_handler(Exception $e){
// show something to the user letting them know we fell down
echo "<h2>Something Bad Happened</h2>";
echo "<p>We fill find the person responsible and have them shot</p>";
// do some logging for the exception and call the kill_programmer function.
}
set_exception_handler("default_exception_handler");
Just adding a bit of extra information here in case someone has the same issue as me.
I use namespaces in my code and I had a class with a function that throws an Exception.
However my try/catch code in another class file was completely ignored and the normal PHP error for an uncatched exception was thrown.
Turned out I forgot to add "use \Exception;" at the top, adding that solved the error.
For
throw new Exception('test exception');
I got 500 (but didn't see anything in the browser), until I put
php_flag display_errors on
in my .htaccess (just for a subfolder).
There are also more detailed settings,
see Enabling error display in php via htaccess only
I want to catch all PHP errors (E_ERROR, E_WARNING, E_NOTICE,..) in a page and log it to MongoDB in order to read and comment better on it.
I found a way to catch last occured error with 'error_get_last' and send it to anywhere i want with 'register_shutdown_function' Handle fatal errors in PHP using register_shutdown_function()
But what if my file have more than one errors, like warnings and notices, how can i get all errors in a file? Is this possible? What i need is something like 'error_get_all'.
Here you can find my code, this code has one fatal error, two warning and one notice:
function shutdown() {
$error = error_get_last();
if ($error['type'] === E_ERROR || $error['type'] === E_WARNING || $error['type'] === E_NOTICE) {
var_dump($error);
}
}
register_shutdown_function('shutdown');
spl_autoload_register('foo');
$x = 5;
$y = 0;
echo 'x/y: ' . $x / $y . '<br/>';
foreach ($noarray as $noelement) {
echo 'no element: ' . $noelement . '<br/>';
}
The answer is to combine solutions:
Use 'set_error_handler' to catch all possible errors it can (see http://php.net/manual/en/function.set-error-handler.php), as well as using the described register_shutdown_function to log the errors which are missed by this.
By doing this, non-fatal errors during runtime will be caught by the custom handler, continuing on until end of script or a fatal error occurs which would be caught by either the custom or the shutdown function depending on type.
Use set_error_handler.
The following error types cannot be handled with a user defined
function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the
file where set_error_handler() is called.
For catching fatal errors and parsing errors you're using right funciton
register_shutdown_function
But when application reach fatal error, or parsing or any error E_ERROR the process of execution ending at that point of the script, so in this case you can catch only one such a error in script.
I will suggest you to use register_shutdown_function just in case to catch fatal errors, and other errors catch with function set_error_handler to catch other errors as warning etc, for exceptions set_exception_handler by that you can easy track all errors in system and validate them also.
If you will write object for error handling then the logic for you can be:
$handler = new Handler();
$handler->handleExceptions(); //using set_exception_handler exceptions
$handler->handleError(E_ALL); //using set_error_handler all other errors
$handler->handleShutdown(); //using register_shutdown_function fatals, parsing
By that you will have options to turn off/on errors and store errors where you need them or send by email from one place, also simple way to get full error for debuging.
May be you want to use a framework like this:
http://code.google.com/p/lagger/
Fatal errors past the first one encountered are impossible to catch, as the PHP interpreter never reaches them (the script terminates after it executes your shutdown handler). Non-fatal errors can be caught (you will need a separate error_handler installed for them in addition to your shutdown handler), PHP won't terminate the script so if you don't terminate it in your error handler either, execution will continue after each non-fatal error and you will catch them all. If you want to still terminate after the entire file has been executed, you might want to keep a flag somewhere, clear it before you include the file and raise it in case of error; after the file has been included, you can test this flag and see if any error has been caught. Keep in mind that the included file will have fully executed at that point (if it did not have any fatal errors) or you might never reach that point (if it has fatal errors).
If you're running untrusted user code, you might be interested in Runkit Sandboxes. You can also take a look at runkit_lint_file() for some pre-include validation.