第 15 章 エラー処理

PHP には、複数のエラーと警告があります。これらを以下に示します。

表 15-1PHPエラーの型

記号説明note
1E_ERROR致命的なランタイムエラー 
2E_WARNINGランタイム警告(致命的でないエラー) 
4E_PARSEコンパイル時のパーサエラー 
8E_NOTICE 実行時の通知(警告よりも重要度は低い)  
16E_CORE_ERROR PHPの初期スタートアップ時に生じた致命的なエラー PHP 4のみ
32E_CORE_WARNING PHPの初期スタートアップ時に生じた警告(致命的でないエラー) PHP 4のみ
64E_COMPILE_ERROR致命的なコンパイルエラーPHP 4のみ
128E_COMPILE_WARNINGコンパイル時の警告(致命的ではないエラー)PHP 4のみ
256E_USER_ERRORユーザが生成したエラーメッセージPHP 4のみ
512E_USER_WARNINGユーザが生成した警告メッセージPHP 4のみ
1024E_USER_NOTICE ユーザが生成した通知メッセージPHP 4のみ
 E_ALL上記のもの全てPHP 4のみ

上記の値(数値または記号のどちらか)は、レポートするエラーの指定する ビットマスクを作成する際に使用されます。複数のエラー型を組み合わせ たりマスクしたりするためにビット演算子を使用する ことが可能です。php.iniで使用できるのは '|', '~', '!', '&' のみであることに注意して下さい。しかし、ビット演算子 でないものは、php3.iniの中で使用可能です。

PHP 4では、 error_reporting のデフォルト設定値は E_ALL & ~E_NOTICEであり、 全てのエラーを表示します。PHP 3 では、デフォルトの設定は、 (E_ERROR | E_WARNING | E_PARSE)であり、 同じことを意味します。しかし、PHP 3 のphp3.ini では定数がサポートされていないため、error_reportingの設定値は数値、 つまり7とする必要があることに注意して下さい。

この初期設定値は、設定ファイルの error_reporting命令で変 更可能です。また、Apacheのhttpd.confファイルの php_error_reporting命令(PHP3ではphp3_error_reporting)で設定すること も可能です。また、実行時にスクリプト内で関数 error_reporting()を使用して設定することも可能です。

警告

PHP 3からPHP 4にコードまたはサーバーを更新する場合、これらの設定および error_reporting()のコールを確認する必要がありま す。新しいエラー型、特にE_COMPILE_ERRORの出力を無効にしたいと思う という人もいると思われます。これを無効にすると空の文書が出力される 可能性があり、この場合には、生じた現象や問題の発見に関するフィード バックは全く得られません。

全ての PHP 式 は、先頭に "@" を付けてコールすることも可能です。 この場合、その式に関するエラーメッセージの出力がオフにされます。 そのような式においてエラーが発生し、 track_errors 機能が有効の 場合、グローバル変数 $php_errormsg からエラー メッセージを得ることができます。

注意 接頭辞 @ エラー制御演算子 は、パースエラーの結果のメッセージ出力は抑 制しません。

警告

現在、@ エラー制御演算子 前置子は、スクリプトの実行を終了するような 致命的なエラーの通知さえも無効にします。他方、これは、ある関数から のエラーを抑制するために @を使用した 場合、この関数が利用可能でなかったり、ミスタイプされている場合でも、 スクリプトはエラーの原因を示さずにそこで終了してしまいます。

以下に、PHPのエラー処理機能の使用例を示します。ファイルに(XMLフォー マットで)情報を記録するエラー処理関数を定義し、致命的なエラーの場合 は開発者にメールを送信します。

例 15-1スクリプトでのエラー処理の使用法

<?php
// 独自のエラー処理を行う
error_reporting(0);

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

    // エラー文字列の連想を定義
    // 実際に考慮するエントリは 2,8,256,512,1024のみ
    $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";
    
    // テスト用
    // echo $err;

    // エラーログに保存し、致命的なエラーの場合はメールを送信する
    error_log($err, 3, "/usr/local/php4/error.log");
    if ($errno == E_USER_ERROR)
        mail("phpdev@mydomain.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;

// いくつかの "vectors" を定義
$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";

?>
上記のコードは、エラー処理とログ関数 の使用法を示す簡単な例です。

error_reporting(), error_log(), set_error_handler(), restore_error_handler(), trigger_error(), user_error()も参照下さい。