Precision about error_log when configured with syslog: the syslog() call is done with severity NOTICE.
エラー処理およびログ記録関数
導入
以下の関数は、エラー処理およびログ記録を行います。これらの関数によ り、独自のエラー処理規則を定義することが可能になり、同時にエラーの ログを記録する方法を修正することが可能になります。これにより、ニーズに 即したエラー出力の変更と拡張が可能になります。
ログ記録関数により他のマシンやemail(またはポケベルのゲートウエイ に!)、システムログ等に直接メッセージを送信することが可能になります。 これにより、ログを行うものを選択したり、アプリケーションやWebサイ トに最も重要な部分をモニタすることが可能になります。
エラー出力関数により、エラーのフィードバックのレベルと種類、 簡単な通知からカスタマイズされた関数までエラーの際に返すもの をカスタマイズすることが可能になります。
要件
外部ライブラリを必要としません。
インストール手順
PHP コアに含まれるため、 追加のインストール無しで使用できます。
実行時設定
php.ini の設定により動作が変化します。
| 名前 | デフォルト | 変更の可否 | 変更履歴 |
|---|---|---|---|
| error_reporting | NULL | PHP_INI_ALL | |
| display_errors | "1" | PHP_INI_ALL | |
| display_startup_errors | "0" | PHP_INI_ALL | PHP 4.0.3 以降で有効です。 |
| log_errors | "0" | PHP_INI_ALL | |
| log_errors_max_len | "1024" | PHP_INI_ALL | PHP 4.3.0 以降で有効です。 |
| ignore_repeated_errors | "0" | PHP_INI_ALL | PHP 4.3.0 以降で有効です。 |
| ignore_repeated_source | "0" | PHP_INI_ALL | PHP 4.3.0 以降で有効です。 |
| report_memleaks | "1" | PHP_INI_ALL | PHP 4.3.0 以降で有効です。 |
| track_errors | "0" | PHP_INI_ALL | |
| html_errors | "1" | PHP_INI_ALL | PHP <= 4.2.3 では PHP_INI_SYSTEM 。PHP 4.0.2 以降で有効です。 |
| docref_root | "" | PHP_INI_ALL | PHP 4.3.0 以降で有効です。 |
| docref_ext | "" | PHP_INI_ALL | PHP 4.3.2 以降で有効です。 |
| error_prepend_string | NULL | PHP_INI_ALL | |
| error_append_string | NULL | PHP_INI_ALL | |
| error_log | NULL | PHP_INI_ALL | |
| warn_plus_overloading | NULL | このオプションは、PHP 4.0.0 以降には存在しません。 |
以下に設定ディレクティブの簡単な説明を示します。
- error_reporting integer
-
エラー出力レベルを設定します。パラメータは、あるビットフィールドを表 す整数か定数名で指定します。このerror_reportingのレベルと定数は、 定義済の定数および php.iniに記述されています。 実行時に設定するには、 error_reporting() 関数を指定してください。 display_errors ディレクティブも参照してください。
PHP 4とPHP 5のデフォルトは E_ALL & ~E_NOTICE です。 この設定はE_NOTICEレベルのエラーは出力されません。 開発時にはこのエラーを表示させたい場合もあるかもしれません。
注意: 開発時にE_NOTICEを有効にすることにはいくつ かの利点があります。デバッグのために、NOTICE メッセージはコード の中のバグの可能性について警告を与えます。例えば、代入されていな い値を使用した場合は、警告を発生します。 これは、書き間違いを見付け、デバッグの時間を節約するために非常 に有用です。NOTICEメッセージは、好ましくないコードに警告します。 例えば、$arr[item] は $arr['item'] と書く方が好ましいです。 これは、PHPが"item"を定数として取り扱うためです。 定数でない場合、PHPは配列の添字ようの文字列と判断します。
注意: PHP 5では新しいエラーレベルE_STRICTを使用できます。 E_STRICTはE_ALLには 含まれないため、明示的にこのエラーレベルを設定する必要があります。 開発中にE_STRICTを有効にすることは いくつかの利点があります。STRICTメッセージは最新かつもっとも有効で 推奨されるコーディングメソッドを使用するように手助けしてくれます。 例えば推奨されない関数を使用したさいに警告を発します。
注意: PHP 定数の、PHP 以外での使用 PHP の定数を、httpd.conf など PHP の外部で使用しても何の意味もありません。外部で使用する場合には、 integer 型の値を指定しなければなりません。 また、エラーレベルはこれからも追加されることがあるので、 最大値 (E_ALL に対応する値) は変わる可能性があります。そこで、E_ALL を指定する場面では 2147483647 のような数を指定するようにしましょう。 これは現状の全ビットに対応した上で、かつ値が将来追加された場合にも対応できます。
PHP 3では、(E_ERROR | E_WARNING | E_PARSE)が デフォルトの設定で、同じことを意味しました。しかし、PHP 3の php3.iniでは定数がサポートされていないため、 error_reportingの設定は数値で指定する必要があり、この場合は、 7とします。
- display_errors string
-
エラーをHTML出力の一部として画面に出力するかどうかを定義します。
"stderr" を指定すると、エラーの内容を stdout (標準出力) ではなく stderr (標準エラー出力) に送ります。この値は PHP 5.2.4 以降で使用可能です。それより前のバージョンでは、 このディレクティブは boolean 型でした。
注意: 開発をサポートする仕組みであり、本番のシステムでは 使用すべきではありません (例えばインターネットに接続されたシステムなど)。
注意: display_errors は実行時にも設定可能(ini_set() 関数を用いて)ですが、スクリプトが致命的(fatal)なエラーを発生した場合は その設定は反映されません。なぜなら、要求されたアクションは 実行されなかったからです。
- display_startup_errors boolean
-
display_errorsをonにした場合でも、PHPの起動シーケンスにおいて発 生したエラーは表示されません。デバッグ時を除き、 display_startup_errorsをoffにしておくことが強く推奨されます。
- log_errors boolean
-
エラーメッセージを、サーバーのエラーログまたはerror_logに記録するかどうかを指定 します。このオプションはサーバーに依存します。
注意: 実用Webサイトではエラー表示を行う変わりにエラーを記録することを 強く推奨します。
- log_errors_max_len integer
-
log_errorsの最大長をキロバイト単位で設定します。 error_log には、 この設定で情報が追加されます。デフォルトは 1024 で、0 を指定すると 最大長の制限は全く適用されなくなります。 この長さはエラーログに記録され、 エラー表示と $php_errormsg に適用されます。
integerを使用する際、 その値はバイト単位で測られます。 この FAQ に記載された 短縮表記を使用することも可能です。 - ignore_repeated_errors boolean
-
繰り返されるメッセージを記録しません。エラーの繰り返しは、 ignore_repeated_sourceが trueに設定されるまで同じファイルの同じ行で発生します。
- ignore_repeated_source boolean
-
メッセージの繰り返しを無視する場合にメッセージのソースを無視しま す。この設定をOnにすると、異なるファイルまたはソース行からの同じ エラーメッセージの繰り返しを記録しなくなります。
- report_memleaks boolean
-
このパラメータをOffにした場合、(stdoutまたはログに)メモリーリー クは表示されなくなります。これは、デバッグ用コンパイル時に error_reportingで E_WARNINGを有効にしている場合のみ有効です。
- track_errors boolean
-
有効にした場合、直近のエラーメッセージが、 $php_errormsg変 数に常に代入されます。
- html_errors boolean
-
エラーメッセージのHTMLタグをオフにします。htmlエラー用の新しい形 式では、ユーザがエラーまたはエラーを発生した関数を説明するページ に導くようクリック可能なメッセージを出力します。これらのリファレ ンスは、docref_root およ び docref_extの設定に依存 します。
- docref_root string
-
新しいエラーフォーマットはエラーやエラーの原因となった関数に関するマニュアル のページの情報を含んでいます。マニュアルのページによっては母国語でダウンロードが 可能であり、このiniディレクティブをマニュアルのローカルコピーのURLにセット することができます。 マニュアルのローカルコピーが'/manual/'でアクセスできるとすると、単に
docref_root=/manual/とするだけです。 ローカルコピーのファイルの拡張子はdocref_ext=.htmlで指定できます。拡張リファレンスを使用することもできます。例えばdocref_root=http://manual/en/またはdocref_root="http://landonize.it/?how=url&theme=classic&filter=Landon&url=http%3A%2F%2Fwww.php.net%2F"が使用できます。ほとんどの場合docref_rootの値の最後を'/'にしようと思うでしょう。 しかし上の二つ目の例を見ではその必要はありません。
- docref_ext string
-
docref_rootを参照して下さ い。
注意: docref_extの値はドット '.'で始まる必要があります。
- error_prepend_string string
-
エラーメッセージの前に出力する文字列。
- error_append_string string
-
エラーメッセージの後に出力する文字列。
- error_log string
-
スクリプトエラーが記録されるファイル名です。 ファイルはウェブサーバユーザで書き込めなければなりません。 syslog が指定されると、エラーはファイルではなく システムロガーに送られます。これは Unix では syslog(3) であり Windows NT ではイベントログのことです。システムロガーは Windows 95 ではサポートされていません。 syslog() も参照してください。 このディレクティブが設定されていない場合、エラーは SAPI エラーロガーに送信されます。これは、例えば Apache のエラーログ、 あるいは CLI なら stderr になります。
- warn_plus_overloading boolean
-
有効な場合、このオプションは加算演算子 (+) が文字列で使用されている場合に警告を出力します。 これにより、文字列結合演算子 (.) を用いて 書き直す必要があるスクリプトを見付けることが容易になります。 このオプションは、PHP 4 には存在しません。
定義済み定数
以下の定数は、PHP コアに含まれており、常に利用可能です。
注意: 以下の定数をphp.iniで使用することができますが、 httpd.confのようなPHPの外部では、 代わりにビットマスク値を使用する必要があります。
| 値 | 定数 | 説明 | 注記 |
|---|---|---|---|
| 1 | E_ERROR (integer) | 重大な実行時エラー。これは、メモリ確保に関する問題のように復帰で きないエラーを示します。スクリプトの実行は中断されます。 | |
| 2 | E_WARNING (integer) | 実行時の警告 (致命的なエラーではない)。スクリプトの実行は中断さ れません。 | |
| 4 | E_PARSE (integer) | コンパイル時のパースエラー。パースエラーはパーサでのみ生成されま す。 | |
| 8 | E_NOTICE (integer) | 実行時の警告。エラーを発しうる状況に遭遇したことを示す。 ただし通常のスクリプト実行の場合にもこの警告を発することがありうる。 | |
| 16 | E_CORE_ERROR (integer) | PHPの初期始動時点での致命的なエラー。E_ERRORに 似ているがPHPのコアによって発行される点が違う。 | PHP 4 より |
| 32 | E_CORE_WARNING (integer) | (致命的ではない)警告。PHPの初期始動時に発生する。 E_WARNINGに似ているがPHPのコアによって発行される 点が違う。 | PHP 4 より |
| 64 | E_COMPILE_ERROR (integer) | コンパイル時の致命的なエラー。E_ERRORに 似ているがZendスクリプティングエンジンによって発行される点が違う。 | PHP 4 より |
| 128 | E_COMPILE_WARNING (integer) | コンパイル時の警告(致命的ではない)。E_WARNINGに 似ているがZendスクリプティングエンジンによって発行される点が違う。 | PHP 4 より |
| 256 | E_USER_ERROR (integer) | ユーザーによって発行されるエラーメッセージ。E_ERROR に似ているがPHPコード上でtrigger_error()関数を 使用した場合に発行される点が違う。 | PHP 4 より |
| 512 | E_USER_WARNING (integer) | ユーザーによって発行される警告メッセージ。E_WARNING に似ているがPHPコード上でtrigger_error()関数を 使用した場合に発行される点が違う。 | PHP 4 より |
| 1024 | E_USER_NOTICE (integer) | ユーザーによって発行される注意メッセージ。E_NOTICEに に似ているがPHPコード上でtrigger_error()関数を 使用した場合に発行される点が違う。 | PHP 4 より |
| 2048 | E_STRICT (integer) | 実行時の注意。コードの相互運用性や互換性を維持するために PHP がコードの変更を提案する。 | PHP 5 より |
| 4096 | E_RECOVERABLE_ERROR (integer) | キャッチできる致命的なエラー。危険なエラーが発生したが、 エンジンが不安定な状態になるほどではないことを表す。 ユーザ定義のハンドラでエラーがキャッチされなかった場合 (set_error_handler() も参照ください) は、 E_ERROR として異常終了する。 | PHP 5.2.0 より |
| 8191 | E_ALL (integer) | サポートされる全てのエラーと警告。PHP < 6 では E_STRICT レベルのエラーは除く。 | PHP 5.2.x では 6143、それより前のバージョンでは 2047 でした。 |
上記の値(数値も論理値も)はどのエラーをレポートするかを指定する ビットマスクを組み立てる。ビット演算子 を使用して値を組み合わせたり特定のエラータイプをマスクすることができる。 php.ini では'|', '~', '!', '^' and '&'のみが解釈されることに 注意すべきであるが、しかし、php3.iniでは ビット演算子は解釈されないことにも注意すべきである。
例
エラー処理機能を PHP で使用するための例を示します。 ファイルに(XML 形式で)情報を記録し、論理的に致命的なエラーの場合に、 開発者に電子メールを送信するようなエラー処理関数を定義します。
Example#1 スクリプト内でのエラー処理
<?php
// 自分のエラーハンドリングを行います
error_reporting(0);
// ユーザーの定義したエラーハンドリング関数
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
// エラーエントリのタイムスタンプ
$dt = date("Y-m-d H:i:s (T)");
// エラー文字列の連想配列を定義します。
// 実際のところ、考慮する必要があるのは
// E_WARNING、E_NOTICE、E_USER_ERROR、
// E_USER_WARNING そして E_USER_NOTICE だけです。
$errortype = array (
E_ERROR => 'Error',
E_WARNING => 'Warning',
E_PARSE => 'Parsing Error',
E_NOTICE => 'Notice',
E_CORE_ERROR => 'Core Error',
E_CORE_WARNING => 'Core Warning',
E_COMPILE_ERROR => 'Compile Error',
E_COMPILE_WARNING => 'Compile Warning',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Runtime Notice',
E_RECOVERABLE_ERROR => 'Catchable Fatal Error'
);
// set of errors for which a var trace will be saved
$user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
$err = "<errorentry>\n";
$err .= "\t<datetime>" . $dt . "</datetime>\n";
$err .= "\t<errornum>" . $errno . "</errornum>\n";
$err .= "\t<errortype>" . $errortype[$errno] . "</errortype>\n";
$err .= "\t<errormsg>" . $errmsg . "</errormsg>\n";
$err .= "\t<scriptname>" . $filename . "</scriptname>\n";
$err .= "\t<scriptlinenum>" . $linenum . "</scriptlinenum>\n";
if (in_array($errno, $user_errors)) {
$err .= "\t<vartrace>" . wddx_serialize_value($vars, "Variables") . "</vartrace>\n";
}
$err .= "</errorentry>\n\n";
// テスト用
// echo $err;
// エラーログを保存し、重大なユーザーエラーは自分にメールする
error_log($err, 3, "/usr/local/php4/error.log");
if ($errno == E_USER_ERROR) {
mail("phpdev@example.com", "Critical User Error", $err);
}
}
function distance($vect1, $vect2)
{
if (!is_array($vect1) || !is_array($vect2)) {
trigger_error("Incorrect parameters, arrays expected", E_USER_ERROR);
return NULL;
}
if (count($vect1) != count($vect2)) {
trigger_error("Vectors need to be of the same size", E_USER_ERROR);
return NULL;
}
for ($i=0; $i<count($vect1); $i++) {
$c1 = $vect1[$i]; $c2 = $vect2[$i];
$d = 0.0;
if (!is_numeric($c1)) {
trigger_error("Coordinate $i in vector 1 is not a number, using zero",
E_USER_WARNING);
$c1 = 0.0;
}
if (!is_numeric($c2)) {
trigger_error("Coordinate $i in vector 2 is not a number, using zero",
E_USER_WARNING);
$c2 = 0.0;
}
$d += $c2*$c2 - $c1*$c1;
}
return sqrt($d);
}
$old_error_handler = set_error_handler("userErrorHandler");
// 未定義定数による警告の生成
$t = I_AM_NOT_DEFINED;
// いくつかの「ベクタ」定義
$a = array(2, 3, "foo");
$b = array(5.5, 4.3, -1.6);
$c = array(1, -3);
// ユーザエラーの生成
$t1 = distance($c, $b) . "\n";
// 他のユーザエラーの生成
$t2 = distance($b, "i am not an array") . "\n";
// 警告の生成
$t3 = distance($a, $b) . "\n";
?>
参考
syslog()も参照してください。
目次
- debug_backtrace — バックトレースを生成する
- debug_print_backtrace — バックトレースを表示する
- error_get_last — 最後に発生したエラーを取得する
- error_log — エラーメッセージを送信する
- error_reporting — 出力する PHP エラーの種類を設定する
- restore_error_handler — 以前のエラーハンドラ関数を回復する
- restore_exception_handler — 以前の例外ハンドラ関数を回復する
- set_error_handler — ユーザ定義のエラーハンドラ関数を設定する
- set_exception_handler — ユーザ定義の例外ハンドラ関数を設定する
- trigger_error — ユーザレベルのエラー/警告/通知メッセージを生成する
- user_error — trigger_error のエイリアス
エラーとログ記録
15-Nov-2007 10:50
11-Oct-2007 04:53
To add to Stephen's note about logging, I found that if I defined the error_log path to be the Apache error log folder (ie: /var/log/httpd/php_error_log), it would still log to Apache's log, not the file I defined.
However, as soon as I moved the log to a location outside of the Apache error log folder, Apache obeyed my php.ini setting and began logging to the file I defined (ie: /var/log/php/php_error_log).
Platform: RHEL 4, Apache 2.0.55, PHP 5.2.2
12-Apr-2007 09:51
In Addition to the hint according error_reporting and display_errors in case that there is a global restriction that prevents showing the errors.
I tried the example of "petrov dot michael () gmail com" like this
<?php
ini_set('display_errors','1');
ini_set('display_startup_errors','1');
error_reporting (E_ALL);
include('index.php');
?>
and it works great, but first I tried it without using the "include"-part. I pasted all at the beginning of my index.php and started it. This will NOT work.
Its highly IMPORTANT that the code to prove is included afterwards.
Hope it helps to prevent more #?!@%! errors. :-)=
19-Jan-2007 08:29
If you are using PHP as an Apache module, your default behavior may be to write PHP error messages 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 think 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.
17-Jan-2007 04:11
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 become run time fatal errors.
09-Jan-2007 10:16
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 taking 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.
05-Aug-2006 12:40
It is totally possible to use debug_backtrace() inside an error handling function. Here, take a look:
<?php
set_error_handler('errorHandler');
function errorHandler( $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\nBacktrace of errorHandler()\n".
print_r( debug_backtrace(), true);
}
function a( )
{
//echo "a()'s backtrace\n".print_r( debug_backtrace(), true);
asdfasdf; // oops
}
function b()
{
//echo "b()'s backtrace\n".print_r( debug_backtrace(), true);
a();
}
b();
?>
Outputs:
<raw>
Into errorhandler() at line 9
---ERRNO---
8
---ERRSTR---
Use of undefined constant asdfasdf - assumed 'asdfasdf'
---ERRFILE---
/home/theotek/test-1.php
---ERRLINE---
23
---ERRCONTEXT---
Array
(
)
Backtrace of errorHandler()
Array
(
[0] => Array
(
[function] => errorhandler
[args] => Array
(
[0] => 8
[1] => Use of undefined constant asdfasdf - assumed 'asdfasdf'
[2] => /home/theotek/test-1.php
[3] => 23
[4] => Array
(
)
)
)
[1] => Array
(
[file] => /home/theotek/test-1.php
[line] => 23
[function] => a
)
[2] => Array
(
[file] => /home/theotek/test-1.php
[line] => 30
[function] => a
[args] => Array
(
)
)
[3] => Array
(
[file] => /home/theotek/test-1.php
[line] => 33
[function] => b
[args] => Array
(
)
)
)
</raw>
So, the first member of the backtrace's array is not really surprising, except from the missing "file" and "line" members.
The second member of the backtrace seem the be a hook inside the zend engine that is used to trigger the error.
Other members are the normal backtrace.
21-Feb-2006 04:52
if you cannot use php 5+ and if you do not know, when your administrator/provider will update to a newer php-version, this could be interesting. otherwise it surely is not. ;-)
if you use the example above "example 1: using error handling in a script" with a php version prior to php 5, the part
<?php
$errortype = array(
// ...
E_STRICT => "Runtime Notice");?>
will throw a notice like
"Use of undefined constant E_STRICT - assumed 'E_STRICT'".
of course one could avoid this problem, with
<?php
if(defined('E_STRICT')) define('E_STRICT', 2048);
?>.
but this _could_ generate problems in future versions of php, if E_STRICT is set to 42 or something else.
for this reason i suggest
<?php
$errortype = array(
E_ERROR => 'error',
E_WARNING => 'warning',
E_PARSE => 'parsing error',
E_NOTICE => 'notice',
E_CORE_ERROR => 'core error',
E_CORE_WARNING => 'core warning',
E_COMPILE_ERROR => 'compile error',
E_COMPILE_WARNING => 'compile warning',
E_USER_ERROR => 'user error',
E_USER_WARNING => 'user warning',
E_USER_NOTICE => 'user notice');
if(defined('E_STRICT'))
$errortype[E_STRICT] = 'runtime notice';
?>.
<?php
// and instead of
// error_reporting(E_ALL | E_STRICT);
// one can use
error_reporting(E_ALL | (defined('E_STRICT')? E_STRICT : 0));
// to avoid that notice.
?>
prosit
seth
29-Nov-2005 02:46
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 masking 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 like the idea of using an integer as the condition in an if statement:
<?php
if (($errno & $user_errors) > 0) {
//...whatever
}
?>
I think that's much more efficient than using _yet another_ array() constuct and an in_array().
If I am wrong, and the E_* constants 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 work, considering the bitwise method should be MUCH more efficient.
23-Jun-2005 06:03
Something to take care of: if track_errors is enabled, $php_errormsg will always be populated with error messages of warning (and possibly notice?) level, regardless of the error_reporting level set.
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 get a log file in each directory you have scripts in. If you want all your error messages 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 get some, but not all, error messages. The file will appear at
c:\php_error.log
and contain internally generated error messages, making it appear that error logging is working. However, log messages requested by error_log() do NOT appear here, or anywhere else, making it appear that the code containing them did not get processed.
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 process apparently can't find "/" - understandably enough - and the message is dropped silently.
28-Jan-2005 07:05
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 27K Jan 27 16:58 php.errors
22-Sep-2004 05:01
As pointed out previously, PHP by default logs to the Apache ErrorLog.
Beware: the messages it logs do not conform to Apache's error log format (missing date and severity fields), so if you use an automated parser on your error logs, you'll want to redirect PHP's errors somewhere else with the error_log directive.
10-Sep-2004 09:20
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 triggered inside that exception handler, you will get a weird error:
"Fatal error: Exception thrown without a stack frame in Unknown on line 0"
This error is not particulary informative, is it? :)
This example below will cause this error.
<?php
class PHPErrorException extends Exception
{
private $context = null;
public function __construct
($code, $message, $file, $line, $context = null)
{
parent::__construct($message, $code);
$this->file = $file;
$this->line = $line;
$this->context = $context;
}
};
function error_handler($code, $message, $file, $line) {
throw new PHPErrorException($code, $message, $file, $line);
}
function exception_handler(Exception $e)
{
$errors = array(
E_USER_ERROR => "User Error",
E_USER_WARNING => "User Warning",
E_USER_NOTICE => "User Notice",
);
echo $errors[$e->getCode()].': '.$e->getMessage().' in '.$e->getFile().
' on line '.$e->getLine()."\n";
echo $e->getTraceAsString();
}
set_error_handler('error_handler');
set_exception_handler('exception_handler');
// Throw exception with an /unkown/ error code.
throw new Exception('foo', 0);
?>
There are however, easy fix for this as it's only cause is sloppy code.
Like 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 messages are intended, this is not the ultimate solution.
So, what is there to do? Make 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.
11-Jan-2002 01:03
A handy errorhandler class can be found at:
http://phpclasses.upperdesign.com/browse.html/package/345
It has several enhancements (report layouts):
* prints the source code fragment where the error encountered,
* prints variable context around error source,
* suppresses error-messages, instead displays an arbitrary HTML or PHP page
* logging to multiple targets and autodetecting target logging
* error messages can be displayed in a separate browser window
* catching errors for runtime generated codes
* debugging variables.