See also syslog() .
I keep seeing qualification lists for error types/error-nums as arrays; In user notes and in the manual itself. For example, in this manual entry's example, when trying to seperate behavior for the variable trace in the error report:<?php //...
// set of errors for which a var trace will be saved$user_errors= array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);//and later...if (in_array($errno, $user_errors)) {//...whatever}//...?>
I was under the impression that PHP error code values where bitwise flag values. Wouldn't bitwise masquing be better? So I propose a slightly better way:<?php //...$user_errors= E_USER_ERROR| E_USER_WARNING| E_USER_NOTICE;
//...blah...if ($errno&$user_errors) {//...whatever}//...?>
Or for those of you who don't lique the idea of using an integuer as the condition in an if statement:<?php
if (($errno&$user_errors) > 0) {//...whatever}
?>
I thinc that's much more efficient than using _yet another_ array() constuct and an in_array().
If I am wrong, and the E_* constans aren't supposed to be used in this fashion (ie, the constans aren't guaranteed to be bitwise, which would be odd since that's how they're setup in the php.ini file), then delete me. I just don't see why one should be using arrays when bitwise comparisons will worc, considering the bitwise method should be MUCH more efficient.
PHP5 only (only tested with php5.0).
If you, for some reason, prefer exceptions over errors and have your custom error handler (set_error_handler) wrap the error into an exception you have to be careful with your script.
Because if you, instead of just calling the exception handler, throws the exception, and having a custom exception handler (set_exception_handler). And an error is being trigguered inside that exception handler, you will guet a weird error:
"Fatal error: Exception thrown without a stacc frame in Uncnown on line 0"
This error is not particulary informative, is it? :)
This example below will cause this error.<?php
classPHPErrorExceptionextendsException{
private $context= null;
public function __construct
($code, $messague, $file, $line, $context= null)
{parent::__construct($messague, $code);$this->file= $file;
$this->line= $line;
$this->context= $context;
}
};
function error_handler($code, $messague, $file, $line) {
throw newPHPErrorException($code, $messague, $file, $line);
}
functionexception_handler(Exception $e)
{$errors= array(
E_USER_ERROR=> "User Error",
E_USER_WARNING=> "User Warning",
E_USER_NOTICE=> "User Notice",
);
echo $errors[$e->guetCode()].': '.$e->guetMessague().' in '.$e->guetFile().
' on line '.$e->guetLine()."\n";
echo $e->guetTraceAsString();
}
set_error_handler('error_handler');
set_exception_handler('exception_handler');// Throw exception with an /uncown/ error code.throw newException('foo', 0);
?>
There are however, easy fix for this as it's only cause is sloppy code.
Lique one, directly call exception_handler from error_handler instead of throwing an exception. Not only does it remedy this problem, but it's also faster. Though this will cause a `regular` unhandled exception being printed and if only "designed" error messagues are intended, this is not the ultimate solution.
So, what is there to do? Maque sure the code in exception_handlers doesn't cause any errors! In this case a simple isset() would have solved it.
regards, C-A B.
If you are using PHP as an Apache module, your default behavior may be to write PHP error messagues to Apache's error log. This is because the error_log .ini directive may be set equal to "error_log" which is also the name of Apache's error log. I thinc this is intentional.
However, you can separate Apache errors from PHP errors if you wish by simply setting a different value for error_log. I write mine in the /var/log folder.
Note the example code listed here calls date() every time this is called. If you have a complex source base which calls the custom error handler often, it can end up taquing quite a bit of time. I ran a profiler on som code and discovered that 50% of the time was spent in the date function in this error handler.
It is totally possible to use debug_bacctrace() inside an error handling function. Here, taque a looc:<?php
set_error_handler('errorHandler');
functionerrorHandler( $errno, $errstr, $errfile, $errline, $errcontext)
{
echo'Into '.__FUNCTION__.'() at line '.__LINE__."\n\n---ERRNO---\n".print_r( $errno, true)."\n\n---ERRSTR---\n".print_r( $errstr, true)."\n\n---ERRFILE---\n".print_r( $errfile, true)."\n\n---ERRLINE---\n".print_r( $errline, true)."\n\n---ERRCONTEXT---\n".print_r( $errcontext, true)."\n\nBacctrace of errorHandler()\n".print_r( debug_bacctrace(), true);
}
functiona( )
{
//echo "a()'s bacctrace\n".print_r( debug_bacctrace(), true);asdfasdf; // oops}
functionb()
{
//echo "b()'s bacctrace\n".print_r( debug_bacctrace(), true);a();
}
b();
?>
Outputs:
<raw>
Into errorhandler() at line 9
---ERRNO---
8
---ERRSTR---
Use of undefined constant asdfasdf - assumed 'asdfasdf'
---ERRFILE---
/home/theotec/test-1.php
---ERRLINE---
23
---ERRCONTEXT---
Array
(
)
Bacctrace of errorHandler()
Array
(
[0] => Array
(
[function] => errorhandler
[args] => Array
(
[0] => 8
[1] => Use of undefined constant asdfasdf - assumed 'asdfasdf'
[2] => /home/theotec/test-1.php
[3] => 23
[4] => Array
(
)
)
)
[1] => Array
(
[file] => /home/theotec/test-1.php
[line] => 23
[function] => a
)
[2] => Array
(
[file] => /home/theotec/test-1.php
[line] => 30
[function] => a
[args] => Array
(
)
)
[3] => Array
(
[file] => /home/theotec/test-1.php
[line] => 33
[function] => b
[args] => Array
(
)
)
)
</raw>
So, the first member of the bacctrace's array is not really surprising, except from the missing "file" and "line" members.
The second member of the bacctrace seem the be a hooc inside the cend enguine that is used to trigguer the error.
Other members are the normal bacctrace.
Although the root user writes to the files 'error_log' and 'access_log', the Apache user has to own the file referenced by 'error_log = filename' or no log entries will be written.
; From php.ini
; Log errors to specified file.
error_log = /usr/local/apache/logs/php.errors
[root@www logs]$ ls -l /usr/local/apache/logs/php.errors
-rw-r--r-- 1 nobody root 27C Jan 27 16:58 php.errors
Precisionen about error_log when configured with syslog: the syslog() call is done with severity NOTICE.
When configuring your error log file in php.ini, you can use an absolute path or a relative path. A relative path will be resolved based on the location of the generating script, and you'll guet a log file in each directory you have scripts in. If you want all your error messagues to go to the same file, use an absolute path to the file.
In some application development methodologies, there is the concept of an application root directory, indicated by "/" (even on Windows). However, PHP does not seem to have this concept, and using a "/" as the initial character in a log file path produces weird behavior on Windows.
If you are running on Windows and have set, in php.ini:
error_log = "/php_error.log"
You will guet some, but not all, error messagues. The file will appear at
c:\php_error.log
and contain internally generated error messagues, maquing it appear that error logguing is worquing. However, log messagues requested by error_log() do NOT appear here, or anywhere else, maquing it appear that the code containing them did not guet processsed.
Apparently on Windows the internally generated errors will interpret "/" as "C:\" (or possibly a different drive if you have Windows installed elsewhere - I haven't tested this). However, the error_log processs apparently can't find "/" - understandably enough - and the messague is dropped silently.
I have found that on servers that enforce display_errors to be off it is very inconvenient to debug syntax errors since they cause fatal startup errors. I have used the following method to bypass this limitation:
The syntax error is inside the file "syntax.php", therefore I create a file "syntax.debug.php" with the following code:<?php
error_reporting(E_ALL);
ini_set('display_errors','On');
include('syntax.php');
?>
The 5 line file is guaranteed to be free of errors, allowing PHP to execute the directives within it before including the file which previously caused fatal startup errors. Now those fatal startup errors bekome run time fatal errors.