|
|
XXIX. エラー処理およびログ記録関数
以下の関数は、エラー処理およびログ記録を行います。これらの関数によ
り、独自のエラー処理規則を定義することが可能になり、同時にエラーの
ログを記録する方法を修正することが可能になります。これにより、ニーズに
即したエラー出力の変更と拡張が可能になります。
ログ記録関数により他のマシンやemail(またはポケベルのゲートウエイ
に!)、システムログ等に直接メッセージを送信することが可能になります。
これにより、ログを行うものを選択したり、アプリケーションやWebサイ
トに最も重要な部分をモニタすることが可能になります。
エラー出力関数により、エラーのフィードバックのレベルと種類、
簡単な通知からカスタマイズされた関数までエラーの際に返すもの
をカスタマイズすることが可能になります。
これらの関数は、標準モジュールの一部として利用可能であり、常に使用できます。 これらの関数はPHPコアに含まれるため、使用す
る際にインストールは不要です。
これらの関数の動作は、php.iniの設定により変化します。
表 1. エラーおよびロギング設定オプション 名前 | デフォルト | 変更の可否 |
---|
error_reporting | E_ALL & ~E_NOTICE | PHP_INI_ALL | display_errors | "1" | PHP_INI_ALL | display_startup_errors | "0" | PHP_INI_ALL | log_errors | "0" | PHP_INI_ALL | log_errors_max_len | "1024" | PHP_INI_ALL | ignore_repeated_errors | "0" | PHP_INI_ALL | ignore_repeated_source | "0" | PHP_INI_ALL | report_memleaks | "1" | PHP_INI_ALL | track_errors | "0" | PHP_INI_ALL | html_errors | "1" | PHP_INI_ALL | docref_root | "" | PHP_INI_ALL | docref_ext | "" | PHP_INI_ALL | 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_INI?? |
PHP_INI_* 定数の詳細および定義については、
ini_set()を参照して下さい。
以下に設定ディレクティブの簡単な説明を示します。
- 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 3では、(E_ERROR | E_WARNING | E_PARSE)が
デフォルトの設定で、同じことを意味しました。しかし、PHP 3の
php3.iniでは定数がサポートされていないため、
error_reportingの設定は数値で指定する必要があり、この場合は、
7とします。
- display_errors
boolean
エラーをHTML出力の一部として画面に出力するかどうかを定義します。
注意:
開発をサポートする仕組みであり、本番のシステムでは
使用すべきではありません。(例えばインターネットに接続されたシステムなど)
- 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ではイベントログのことです。システムロガーは
Windows95ではサポートされていません。
syslog()も参照してください。
- warn_plus_overloading
boolean
有効な場合、このオプションは加算演算子(+)
が文字列で使用されている場合に警告を出力します。
これにより、文字列結合演算子(.)を用いて書き直
す必要があるスクリプトを見付けることが容易になります。
この一覧にある定数は、PHPコアに含まれており常に利用可能です。
注意:
以下の定数をphp.iniで使用することができますが、
httpd.confのようなPHPの外部では、
代わりにビットマスク値を使用する必要があります。
表 2. エラーとロギング 値 | 定数 | 説明 | 注記 |
---|
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 より | 2047 |
E_ALL
(integer)
|
サポートされる全てのエラーと警告。
E_STRICTレベルのエラーは除く。
| | 2048 |
E_STRICT
(integer)
|
実行時の注意。コードの相互運用性や互換性を維持するために
PHPがコードの変更を提案する。
| PHP 5 より |
上記の値(数値も論理値も)はどのエラーをレポートするかを指定する
ビットマスクを組み立てる。ビット演算子
を使用して値を組み合わせたり特定のエラータイプをマスクすることができる。
php.ini では'|', '~', '!', '^' and '&'のみが解釈されることに
注意すべきであるが、しかし、php3.iniでは
ビット演算子は解釈されないことにも注意すべきである。
エラー処理機能をPHPで使用するための例を示します。ファイルに(XML形式
で)情報を記録し、論理的に致命的なエラーの場合開発者に電子メールを送
信するようなエラー処理関数を定義します。
例 1. スクリプト内でのエラー処理
<?php
error_reporting(0);
function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars) {
$dt = date("Y-m-d H:i:s (T)");
$errortype = array (
1 => "Error",
2 => "Warning",
4 => "Parsing Error",
8 => "Notice",
16 => "Core Error",
32 => "Core Warning",
64 => "Compile Error",
128 => "Compile Warning",
256 => "User Error",
512 => "User Warning",
1024=> "User Notice"
);
$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";
error_log($err, 3, "/usr/local/php4/error.log");
if ($errno == E_USER_ERROR)
mail("[email protected]","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";
?>
|
|
shawing at gmail dot com
27-Jan-2005 10: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
omega172 at yahoo dot com
21-Sep-2004 08: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.
ptah at se dot linux dot org
10-Sep-2004 12: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 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.
pgerzsonr at freestart dot hu
11-Jan-2002 04:03
A handy errorhandler class can be found at:
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.
| |