PHP's error levels - php

The only error level in PHP that will halt the script but can be caught and dealt with have to be triggered with the trigger_error() function correct? I'm referring to the "E_USER_ERROR" error level. The "E_ERROR" error will simply halt the script and I can't do anything about it as the developer.

E_ERROR will simply stop the script. It's meant to be used for:
Fatal run-time errors. These indicate errors that can not be recovered from, such as a memory allocation problem. Execution of the script is halted.
Ref
You cannot handle the following other error types for similar reasons:
E_PARSE
E_CORE_ERROR
E_CORE_WARNING
E_COMPILE_ERROR
E_COMPILE_WARNING
set_error_handler() however can handle the follow errors:
E_WARNING
E_NOTICE
E_USER_ERROR (using trigger_error)
E_USER_WARNING (using trigger_error)
E_USER_NOTICE (using trigger_error)
E_STRICT
E_RECOVERABLE_ERROR

You can catch E_ERROR using a shutdown script
from my posting http://jarofgreen.wordpress.com/2011/02/04/catching-php-errors/
register_shutdown_function(‘x’);
function x() {
$error = error_get_last();
if ($error) {
// deal with $error['file'],$error['line'],$error['message'],$error['type']
}
}

You can create your own error handling and halt the script and actually do anything you want when an error occurs.
set_error_handler()

Not really sure what your driving at or trying to do here, but if you're looking for a way to "catch" and deal with 'errors' - Maybe look into exceptions.
From PHP Manual on Exceptions
An exception can be thrown, and caught
("catched") within PHP. Code may be
surrounded in a try block, to
facilitate the catching of potential
exceptions. Each try must have at
least one corresponding catch block.
Multiple catch blocks can be used to
catch different classes of exeptions.
Normal execution (when no exception is
thrown within the try block, or when a
catch matching the thrown exception's
class is not present) will continue
after that last catch block defined in
sequence. Exceptions can be thrown (or
re-thrown) within a catch block.

Related

Severity of exception codes

I am trying to sort out error and exception handlers. With a fatal error, I send myself a text message, and with other errors I get an email. (I added the arrays at the end in case they may be useful.)
For errors there is https://php.net/manual/en/errorfunc.constants.php I but cannot find anything similar for exceptions.
I believe I can set my own exception values but are there agreed severity levels for general exceptions, PDOExceptions etc. The only place I find severity mentioned is in ErrorException. (I only use PDOExceptions at the moment but am trying to catch other "general" ones.)
Is a severity helper chart available somewhere? I freely admit I am struggling with exceptions.
PS I had a look at https://www.php.net/manual/en/errorexception.getseverity.php but that looks like it is for errors being sent as exceptions. I am quite confused now.
Error code arrays in case they are useful.
$phpErrorCodes = array (
1 => "E_ERROR",
2 => "E_WARNING",
4 => "E_PARSE",
8 => "E_NOTICE",
16 => "E_CORE_ERROR",
32 => "E_CORE_WARNING",
64 => "E_COMPILE_ERROR",
128 => "E_COMPILE_WARNING",
256 => "E_USER_ERROR",
512 => "E_USER_WARNING",
1024 => "E_USER_NOTICE",
2048 => "E_STRICT E_ALL",
4096 => "E_RECOVERABLE_ERROR",
8192 => "E_DEPRECATED",
16384=> "E_USER_DEPRECATED",
32767=> "E_ALL");
$phpErrorCodesFatal = array (
1 => "E_ERROR",
16 => "E_CORE_ERROR",
64 => "E_COMPILE_ERROR",
4096 => "E_RECOVERABLE_ERROR");
$phpErrorCodesFatalNumberOnly = array (
1 ,
16 ,
64 ,
4096);
//4096 recoverable but dangerous so treated as fatal
Exceptions
Let me try to clarify some misconceptions here.
Are there severity codes for exceptions?
No. All exceptions are severe.
An exception will stop the execution of your script. They are used to prevent the execution of the code which follows if the preceding code could not be executed.
How do I know if they are important?
All exceptions are important. When an exception is triggered it tells you as a developer that something unexpected has happened in the code. The code which you have written simply did not anticipate this happening and to prevent undefined behaviour it should stop processing immediately.
Unhandled exceptions would show up as PHP Warning. - mario
That is not true. Any unhandled exception will be converted to PHP Fatal error. If your application doesn't know how to handle an exceptional situation then PHP must immediately stop! It is not a warning you can ignore or silence; it's a fatal error.
As a rule of thumb I should treat exceptions as fatal errors?
Not necessarily. In rare cases a developer might expect a particular piece of code to throw an exception, which is possible to recover from or work around. The code logic anticipates something going wrong and has a way around the problem. If the exception is caught and handled this will not result in a fatal error.
The difference between an exception and a fatal error is that you can catch and recover from an exception, but not from a fatal error.
So if I don't do anything then exceptions turn to errors.
If you have not caught the exception and you do not have your own error handled implemented then PHP will default to the built-in error handler. The logic is that it will stop the script and throw an error with the exception as a message. This error will then, based on your configuration settings, either be logged on the server or displayed to the user.
Errors
PHP has a bad history. One of the problems with early PHP versions was that it was very lenient when it comes to badly written code. It would either try to guess what the correct action should be or merely warn the user about some serious problem. The outcome of this was that a lot of developers learned to simply ignore the warnings, notices and sometimes even errors.
With PHP 7 few things have changed.
PHP 7 changes how most errors are reported by PHP. Instead of reporting errors through the traditional error reporting mechanism used by PHP 5, most errors are now reported by throwing Error exceptions. An error is still not an exception, but it behaves like one. You can catch the error and if you don't you will still see "Fatal error: Uncaught Error: ...".
Modern PHP functionalities will now use exceptions. This means that userland code should also try to follow the same approach. Throw an exception when your code should stop the execution (don't use die/exit for this) and only catch them when when you know how to recover.
With future PHP releases the notices and warnings might be changed to Error exceptions. Don't ignore them now. Treat all of them as severe problems in your code and fix them now.
As per the comments, the general advice with exceptions is that you should catch them all - in that sense, all unhandled exceptions are severe.
However, you could still classify exceptions in your system in the way that you want. Let's say that at the top level of your app you have a call that enters the main app:
try
{
$this->mainApp();
}
catch (SeriousRuntimeException $e)
{
$this->handleSeriousError($e);
}
catch (TrivialRuntimeException $e)
{
$this->handleTrivialError($e);
}
Then in your code you can throw a SeriousRuntimeException or a TrivialRuntimeException as you see fit. In some cases you will have external exceptions to deal with, and you will need to convert them like so:
try
{
$this->databaseOperation();
}
catch (PDOException $e)
{
// Copy the exception properties that are important to you.
// Throw the appropriate severity based on what handler you
// want to run.
throw new SeriousRuntimeException($e->getMessage());
}
In this example I assume that both exception types are fatal, but they are handled differently. It is conceivable that you could have an exception type that is so trivial that the app keeps running (e.g. in a listener loop - it logs the fault and then carries on).

How do I capture require errors + error_handlers

I am trying to use the set_error_handler function to capture require errors.
while my custom error_handler is being used, the context seems completely off, although the trace is correct.
<?php
function error_handler($errno, $errstr, $errfile, $errline){
throw new Exception($errstr);
}
set_error_handler('error_handler');
try{
trigger_error("somethign",E_USER_NOTICE);
}catch(Exception $e){
echo "I got caught";
}
try{
require "something/that/does/not/exists.php";
}catch(Exception $e){
echo "I got caught";
}
As can be seen, when I trigger the first error, it triggers the error_handler which in turn is throwing an exception. Which is caught in the first try-catch.
The second time, where I try to include an un-existing file, again the error_handler is used, but the exception is not caught.
What is going on here?
I am using php 5.5.*
Tested in CLI mode.
Just read the documentation:
require is identical to include except upon failure it will also
produce a fatal E_COMPILE_ERROR level error. In other words, it will
halt the script
(http://php.net/manual/en/function.require.php)
That means, the script execution is aborted when this error is encountered. Your custom error handler will be used but throw will be ignore because that assumes further execution which is not allowed at this point.
It's important to remember that there's two general types of errors with PHP
Processing errors are caught when your program runs
Compile errors occur when you have bad syntax or when you try to do something impossible
In your case, require is a compile error. It will not execute your user defined function because it will never get that far. The compiler can't include the bad file and will fail out.

PhP Exception message shown despite been caught by the exception handler

I have set an exception handler in my PhP program using set_exception_handler() and it actually works fine. In the sense, it does catch exceptions not otherwise handled by me, and as provided in the handler, logs the exception details. So, why am I complaining? Problem is that in addition to logging the correct details with file name and line number in the exception handler, it also displays the following message in the browser:
Fatal error: Exception thrown without a stack frame in Unknown on line 0
My belief is that perhaps this specific exception message is coming from stdout stream while the exceptions been caught by the handler are from the stderr stream. The other possibility is that the above message is emitted by the error handler module and not the exception handler module of PhP. In any event, I would like all exception messages to go to one handler. I also have a error handler set as follows:
set_error_handler('SS_error_handler', E_ALL);
How are such situations handled? Is the Fatal error message coming from PhP's error message reporting module? If so, is there an overlap between the exception handler and the error handler in the sense that they both get triggered on certain errors/exceptions? If relevant, I would like to add that this specific exception is thrown be a MySQL PDO statement.
Any explanation would be appreciated.
Please reference the docs: http://php.net/manual/en/function.set-error-handler.php
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.
Hence, you cannot use set_error_handler to catch exceptions, you should use proper try { } catch { } blocks.
add # character at the beginning of line that causes errors, that will silence it.
also you can ini_set('display_errors', 0), that will silence everyone :)
but usual people just try{} catch ( e) { trigger_error(e, E_USER_ERROR);}

Is it possible to catch all PHP errors occured in a file

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.

How to catch undefined functions with set_error_handler in PHP

I'm taking the leap: my PHP scripts will ALL fail gracefully!
At least, that's what I'm hoping for...`
I don't want to wrap (practically) every single line in try...catch statements, so I think my best bet is to make a custom error handler for the beginning of my files.
I'm testing it out on a practice page:
function customError($level,$message,$file,$line,$context) {
echo "Sorry, an error has occured on line $line.<br />";
echo "The function that caused the error says $message.<br />";
die();
}
set_error_handler("customError");
echo($imAFakeVariable);
This works fine, returning:
Sorry, an error has occurred on line 17. The function that caused the
error says Undefined variable: imAFakeVariable.
However, this setup doesn't work for undefined functions.
function customError($level,$message,$file,$line,$context) {
echo "Sorry, an error has occured on line $line.<br />";
echo "The function that caused the error says $message.<br />";
die();
}
set_error_handler("customError");
imAFakeFunction();
This returns:
Fatal error: Call to undefined function: imafakefunction() in
/Library/WebServer/Documents/experimental/errorhandle.php on line 17
Why isn't my custom error handler catching undefined functions? Are there other problems that this will cause?
set_error_handler is designed to handle errors with codes of: E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE. This is because set_error_handler is meant to be a method of reporting errors thrown by the user error function trigger_error.
However, I did find this comment in the manual that may help you:
"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."
This is not exactly true. set_error_handler() can't handle them, but ob_start() can handle at least E_ERROR.
<?php
function error_handler($output)
{
$error = error_get_last();
$output = "";
foreach ($error as $info => $string)
$output .= "{$info}: {$string}\n";
return $output;
}
ob_start('error_handler');
will_this_undefined_function_raise_an_error();
?>
Really though these errors should be silently reported in a file, for example. Hopefully you won't have many E_PARSE errors in your project! :-)
As for general error reporting, stick with Exceptions (I find it helpful to make them tie in with my MVC system). You can build a pretty versatile Exception to provide options via buttons and add plenty of description to let the user know what's wrong.
I guess you needs to use register_shutdown_function also
For example:
register_shutdown_function( array( $this, 'customError' ));.
function customError()
{
$arrStrErrorInfo = error_get_last();
print_r( $arrStrErrorInfo );
}
From the documentation (emphasis added):
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.
Calling undefined functions triggers an E_ERROR, thus it can not be handled by the error callback (or by exception handlers for that matter). All that you can do is set error_reporting to 0.
PS, if you are rolling your own error handler, you should take care to handle correctly the # operator. From the documentation (emphasis added):
It is important to remember that the standard PHP error handler is completely bypassed. error_reporting() settings will have no effect and your error handler will be called regardless - however you are still able to read the current value of error_reporting and act appropriately. Of particular note is that this value will be 0 if the statement that caused the error was prepended by the # error-control operator.
Why isn't my custom error handler catching undefinedd functions? Are there other problems that this will cause?
At a guess, I'd say that undefined function errors travel through a different execution path than other error types. Perhaps the PHP designers could tell you more, except I doubt PHP is in any way designed.
If you'd like your scripts to fail gracefully while still writing them PHP-style, try putting the entire page in a function and then call it within a try..catch block.
I've been playing around with error handling for some time and it seems like it works for the most part.
function fatalHandler() {
global $fatalHandlerError, $fatalHandlerTitle;
$fatalHandlerError = error_get_last();
if( $fatalHandlerError !== null ) {
print($fatalHandlerTitle="{$fatalHandlerTitle} | ".join(" | ", $fatalHandlerError).
(preg_match("/memory/i", $fatalHandlerError["message"]) ? " | Mem: limit ".ini_get('memory_limit')." / peak ".round(memory_get_peak_usage(true)/(1024*1024))."M" : "")."\n".
"GET: ".var_export($_GET,1)."\n".
"POST: ".var_export($_POST,1)."\n".
"SESSION: ".var_export($_SESSION,1)."\n".
"HEADERS: ".var_export(getallheaders(),1));
}
return $fatalHandlerTitle;
}
function fatalHandlerInit($title="phpError") {
global $fatalHandlerError, $fatalHandlerTitle;
$fatalHandlerTitle = $title;
$fatalHandlerError = error_get_last();
set_error_handler( "fatalHandler" );
}
Now I have an issue where if the memory is exhausted, it doesn't report it every time. It seems like it depends on how much memory is being used.
I did a script to load a large file (takes ~6.6M of memory) in an infinite loop.
Setup1:
ini_set('memory_limit', '296M');
fatalHandlerInit("testing");
$file[] = file("large file"); // copy paste a bunch of times
In this case I get the error to be reports and it dies on 45 file load.
Setup2 - same but change:
ini_set('memory_limit', '299M');
This time I don't get an error and it doesn't even call my custom error function. The script dies on the same line.
Does anyone have a clue why and how to go around that?
Very interesting thing that I've discovered today as I was facing the similar problem. If you use the following - it will catch the error with your custom error handler function / method:
ini_set('display_errors', 'Off');
error_reporting(-1);
set_error_handler(array("Cmd\Exception\Handler", "getError"), -1 & ~E_NOTICE & ~E_USER_NOTICE);
By setting 'display_errors' to 'Off' you can catch still catch them with the handler.
At a guess, I'd say that undefined function errors travel through a different execution path than other error types. Perhaps the PHP designers could tell you more, except I doubt PHP is in any way designed.

Categories