XXXII. エラー処理およびログ記録関数

導入

以下の関数は、エラー処理およびログ記録を行います。これらの関数によ り、独自のエラー処理規則を定義することが可能になり、同時にエラーの ログを記録する方法を修正することが可能になります。これにより、ニーズに 即したエラー出力の変更と拡張が可能になります。

ログ記録関数により他のマシンやemail(またはポケベルのゲートウエイ に!)、システムログ等に直接メッセージを送信することが可能になります。 これにより、ログを行うものを選択したり、アプリケーションやWebサイ トに最も重要な部分をモニタすることが可能になります。

エラー出力関数により、エラーのフィードバックのレベルと種類、 簡単な通知からカスタマイズされた関数までエラーの際に返すもの をカスタマイズすることが可能になります。

要件

外部ライブラリを必要としません。

インストール手順

PHP コアに含まれるため、 追加のインストール無しで使用できます。

実行時設定

php.ini の設定により動作が変化します。

表 1. エラーおよびロギング設定オプション

名前デフォルト変更の可否変更履歴
error_reportingNULLPHP_INI_ALL 
display_errors"1"PHP_INI_ALL 
display_startup_errors"0"PHP_INI_ALLPHP 4.0.3 以降で有効です。
log_errors"0"PHP_INI_ALL 
log_errors_max_len"1024"PHP_INI_ALLPHP 4.3.0 以降で有効です。
ignore_repeated_errors"0"PHP_INI_ALLPHP 4.3.0 以降で有効です。
ignore_repeated_source"0"PHP_INI_ALLPHP 4.3.0 以降で有効です。
report_memleaks"1"PHP_INI_ALLPHP 4.3.0 以降で有効です。
track_errors"0"PHP_INI_ALL 
html_errors"1"PHP_INI_ALLPHP <= 4.2.3 では PHP_INI_SYSTEM 。PHP 4.0.2 以降で有効です。
docref_root""PHP_INI_ALLPHP 4.3.0 以降で有効です。
docref_ext""PHP_INI_ALLPHP 4.3.2 以降で有効です。
error_prepend_stringNULLPHP_INI_ALL 
error_append_stringNULLPHP_INI_ALL 
error_logNULLPHP_INI_ALL 
warn_plus_overloadingNULLPHP_INI?? 
PHP_INI_* 定数の詳細および定義については 付録G を参照してください。

以下に設定ディレクティブの簡単な説明を示します。

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_STRICTE_ALLには 含まれないため、明示的にこのエラーレベルを設定する必要があります。 開発中にE_STRICTを有効にすることは いくつかの利点があります。STRICTメッセージは最新かつもっとも有効で 推奨されるコーディングメソッドを使用するように手助けしてくれます。 例えば推奨されない関数を使用したさいに警告を発します。

PHP 3では、(E_ERROR | E_WARNING | E_PARSE)が デフォルトの設定で、同じことを意味しました。しかし、PHP 3の php3.iniでは定数がサポートされていないため、 error_reportingの設定は数値で指定する必要があり、この場合は、 7とします。

display_errors boolean

エラーをHTML出力の一部として画面に出力するかどうかを定義します。

注意: 開発をサポートする仕組みであり、本番のシステムでは 使用すべきではありません。(例えばインターネットに接続されたシステムなど)

注意: 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() も参照してください。

warn_plus_overloading boolean

有効な場合、このオプションは加算演算子 (+) が文字列で使用されている場合に警告を出力します。 これにより、文字列結合演算子 (.) を用いて 書き直す必要があるスクリプトを見付けることが容易になります。 このオプションは、PHP 4 には存在しません。

定義済み定数

以下の定数は、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. スクリプト内でのエラー処理

// 自分のエラーハンドリングを行います
error_reporting(0);

// ユーザーの定義したエラーハンドリング関数
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
    // エラーエントリのタイムスタンプ
    $dt = date("Y-m-d H:i:s (T)");

    // define an assoc array of error string
    // in reality the only entries we should
    // consider are E_WARNING, E_NOTICE, E_USER_ERROR,
    // E_USER_WARNING and 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"
                );
    // 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_log -- エラーメッセージを送信する
error_reporting -- 出力する PHP エラーの種類を設定する
restore_error_handler -- 以前のエラーハンドラ関数を回復する
restore_exception_handler --  以前の例外ハンドラ関数を回復する
set_error_handler --  ユーザ定義のエラーハンドラ関数を設定する
set_exception_handler --  ユーザ定義の例外ハンドラ関数を設定する
trigger_error -- ユーザレベルのエラー/警告/通知メッセージを生成する
user_error -- trigger_error() のエイリアス