set_error_handler

制御構造例外処理

概要

 状態:-  閲覧数:3,653  投稿日:2014-03-03  更新日:2014-03-19  
ユーザー定義のエラーハンドラ関数を設定する標準関数
・「実行時のエラー処理をユーザが定義する」ために、「ユーザ定義のエラーハンドラ関数」を設定

構文
mixed set_error_handler ( callback $error_handler [, int $error_types = E_ALL | E_STRICT ] )
set_error_handler( エラー処理関数 [, エラータイプ ])
・第 1 引数 … スクリプトのエラー処理を行うユーザ関数 (error_handler)を指定
・第 2 引数 … エラー出力レベルを指定(エラー処理関数の起動制御に使用)。なお、エラータイプを指定しない場合は、エラー処理関数が全てのエラーで起動
※エラー処理関数が FALSE を返さない限り、この引数 で指定した型のエラーでは PHP 標準のエラーハンドラは起動しないので注意が必要
エラー処理関数 ( エラーレベル , 発生したエラーメッセージ[, エラーが発生したPHPスクリプト名[, エラーが発生した行番号 [, エラーが発生したスコープ内での全ての変数を格納した配列]]] )
・第 1 引数 … 発生させる エラーの出力レベルを整数(ビット値)で格納
・第 2 引数 … 発生したエラーメッセージを文字列で格納
・第 3 引数 … オプション/エラーが発生したファイルの名前を文字列で格納
・第 4 引数 … オプション/エラーが発生した行番号を整数で格納
・第 5 引数 … オプション/エラーが発生したスコープ内でのすべての変数を格納した 配列。 ユーザエラーハンドラは、この引数を書き換えては いけない
※error_reporting() の設定にかかわらず、どのような場合でもユーザが設定したエラー処理関数(エラーハンドラ)がコールされる。但し、この場合でも エラー処理関数(エラーハンドラ)で error_reporting() のカレントの値を読み込み、それに合わせ適切に動作させることは可能。なお、エラーを発生した命令の前に @ エラー制御演算子 が付加されている場合、この値は 0 となる。
また、以下のエラータイプは、ユーザ定義の関数では扱えない。 E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING および set_error_handler() がコールされたファイルで発生した 大半の E_STRICT。つまり、Fatal Error は処理できない(ちなみに同じFatal Error でも、例外が投げられる時もあれば、投げられないときもある)


詳細


仕組
・エラーイベントを処理する「エラーハンドラ」(デフォルトのエラーハンドラはエラーメッセージを表示)を、「ユーザー定義エラーハンドラ」に置き換える

メリット
・PHPスクリプトでエラーハンドラを記述できるため、特定のエラー発生時に管理者にメールを送信を行うなどの必要なエラー処理を行うことができる

特徴
・set_error_handler が呼び出された後、エラーが発生した場合、set_error_handler で登録した関数でエラー処理が行われる
・一度set_error_handler が呼び出されると restore_error_handler を使ってエラー処理を解除するまで、エラーを捕捉し続ける
・例外をスローするのは、set_error_handler()で指定した関数内1箇所のみ

処理の流れ
・1.tryブロック内の処理でエラー発生
・2.発生したエラーは、「set_error_handler()の引数で指定した関数」で処理
・3.同関数内より、例外をスロー(スロー記述は、この一箇所だけ)

「try~catch」「set_error_handler」を組み合わせるメリット

 閲覧数:1,001 投稿日:2014-03-05 更新日:2014-03-12 

try~catchだけ


何度もスロー記述をしなければいけない
public function hoge() {
   try {
       if (TRUE === $error) {
           throw new Exception($e);
       }
       if (~~~) {
           throw new Exception($e);
       }
   } catch(Exception $e) {

   }
}



set_error_handler()も利用


スロー記述は一箇所だけ
public static function my_error_handler($errno,$errstr,$errfile,$errline) {
   throw new Exception($errst,($errno);
}

public function hoge() {
   set_error_handler("クラス名::my_error_handler");
   try {

   } catch(Exception $e) {

   }
   restore_error_handler();
}



static


set_error_handler() は staticで書いておけば、下記何れでも利用可
・set_error_handler("クラス名::my_error_handler");
・set_error_handler("self::my_error_handler");
・set_error_handler(array($this,'my_error_handler'));

コード例

 閲覧数:861 投稿日:2014-03-12 更新日:2014-03-23 

tryブロックの外


try~catch未利用
・set_exception_handler関数を利用(Exceptionクラスは利用しているものの、try~catchは利用せず、例外を明示的に投げているだけ)
・set_exception_handler関数では、例外が捕捉されなかった場合のデフォルトの例外ハンドラを指定することができる
・下記の例では、tryブロックの外で例外を投げているため、通常はFatal errorとなるが、set_exception_handler()で例外ハンドラを指定しているため、exceptionHandler関数が呼ばれている
・注意すべき点として、例外ハンドラの処理後にPHPプログラムは実行を終了してしまう
function exceptionHandler($e)
{
echo $e->getMessage(), PHP_EOL;
}
set_exception_handler('exceptionHandler');
throw new Exception('catchされなかった例外');
echo 'end', PHP_EOL;
// 出力:catchされなかった例外

・結果
catchされなかった例外


ファイルオープン


Warning:エラー(ファイルオープンエラー)のエラーハンドリング
function test_error_handler($errorno,$errstr,$errfile,$errline,$errcontext) {
switch ($errno) {
case E_ERROR://ユーザ定義関数では、E_ERRORは扱えない
echo "致命的エラー:" . $errorno . " ユーザー作成エラーメッセージ:" . $errstr. " エラー発生行数:" . $errline."<br />";
break;
default:
echo "その他のエラー エラーコード:" . $errorno . "<br> ユーザー作成エラーメッセージ:" . $errstr . "<br> エラー発生行数:" . $errline."<br>";
break;
}
}

set_error_handler("test_error_handler");
$fd = fopen("c:/temp/azz.txt","r");

・結果
その他のエラー エラーコード:2
ユーザー作成エラーメッセージ:fopen(c:/temp/azz.txt): failed to open stream: No such file or directory
エラー発生行数:34


0除算


Warning:エラー(0 除算)のエラーハンドリング
・エラータイプにE_ALL引数を指定
function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
    echo "[$errno] $errstr ($errline)行目\n";
}

set_error_handler( 'my_error_handler', E_ALL );
$i = 5/0;

・結果
[2] Division by zero (29)行目

try~catch利用
・set_error_handler()の引数で指定したメソッドで、Exceptionを継承した例外クラスのインスタンスオブジェクトをスロー
・1.tryブロック内の処理でエラー発生
・2.発生したエラーは、「set_error_handler()の引数で指定したメソッド」で処理
・3.同メソッドより、「Exceptionを継承した例外クラスのインスタンスオブジェクト」をスロー
・4.例外キャッチ
function errorHandler($errno, $errstr, $errfile, $errline) {
throw new Exception($errstr, $errno);//3.例外をスロー
}

set_error_handler('errorHandler');//2.エラーを「引数で指定した関数」で処理

try {
5/0;//1.… 0除算。Warningエラー発生
} catch (Exception $e) {//4.例外をキャッチ
echo $e->getMessage();
}

・処理結果
Division by zero

・set_error_handler()は、Warning:エラー(0 除算)をエラーハンドリング出来るが、Fatal error: エラー(未定義関数呼び出し/致命的かつ復帰できない場合)は、エラーハンドリング出来ない。これは Fatal error (致命的エラー) の箇所で、スクリプトが終了処理してしまい、ユーザー定義のエラーハンドラ関数が呼び出されないため
function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
// echo "[$errno] $errstr $errfile($errline)\n";
echo "[$errno] $errstr ($errline)\n";
}

//set_error_handlerがない状態
$i = 5/0;//0 除算でエラー発生→Warning:
//foo();//未定義関数でエラー発生→Fatal error:ここで処理終了するため、コメントアウト

set_error_handler( 'my_error_handler', E_ALL );

$i = 5/0;//0 除算でエラー発生→Warning:
foo();//未定義関数でエラー発生→Fatal error:ここで処理終了

上記のようなエラーハンドラ関数で処理できないエラーについては、スクリプトのシャットダウン関数を利用して処理。シャットダウン関数は register_shutdown_function 関数で指定


クラス


 
echo 'phpversion : ' . phpversion() . "\n<br>";

//
// PHPエラーを例外(Exception)へ変換
//
class MyException extends Exception
{
public function __construct($errno, $errstr, $errfile, $errline)
{

p($errno );  //8…エラー出力レベル(ビット値)
p($errstr );  //Undefined variable: xxx
//p($errfile );  //エラーファイル
p($errline );  //エラー行数

// エラー定数(エラー出力レベル/ビット値)と文字列のマッピング(連想配列)
$errlev = array(
E_USER_ERROR   => 'FATAL',
E_ERROR        => 'FATAL',
E_USER_WARNING => 'WARNING',
E_WARNING      => 'WARNING',
E_USER_NOTICE  => 'NOTICE',
E_NOTICE       => 'NOTICE',
E_STRICT       => 'E_STRICT'
);

p($errlev );  
/*出力
Array
(
   [256] => FATAL
   [1] => FATAL
   [512] => WARNING
   [2] => WARNING
   [1024] => NOTICE
   [8] => NOTICE
   [2048] => E_STRICT
)
*/

$add_msg= (string)$errno;//8

p($errlev[$errno]);//NOTICE…取得した「ビット値」を、用意した連想配列のキーへ対応させ、値を取得

if (isset($errlev[$errno])) {
$add_msg = $errlev[$errno] . ' : ';
}
parent::__construct($add_msg . $errstr, $errno);//(エラー定数+)エラーメッセージ,例外コード
$this->file = $errfile;//プロパティへのセッター
$this->line = $errline;//プロパティへのセッター
}
}

function errorHandler($errno, $errstr, $errfile, $errline)
{
throw new MyException($errno, $errstr, $errfile, $errline);
}
set_error_handler('errorHandler');


//
// 以下テストコード
//

error_reporting(E_ALL|E_STRICT);//E_ALL+E_STRICT

function funcA()
{
echo $xxx; // 意図的に、未定義の変数を参照しNOTICEを発生させる
}

try {
funcA();
}
catch (Exception $e) {
echo "--------------\n<br><pre>";
echo $e . "</pre>\n<br>";
echo "--------------\n<br>";
}
/*出力
phpversion : 5.3.8

8

Undefined variable: xxx

85

Array
(
   [256] => FATAL
   [1] => FATAL
   [512] => WARNING
   [2] => WARNING
   [1024] => NOTICE
   [8] => NOTICE
   [2048] => E_STRICT
)

NOTICE

--------------

exception 'MyException' with message 'NOTICE : Undefined variable: xxx' in /○○/exception/13.php:85
Stack trace:
#0 /○○/exception/13.php(85): errorHandler(8, 'Undefined varia...', '/○○/ibj/pu...', 85, Array)
#1 /○○/exception/13.php(89): funcA()
#2 {main}
*/



Exceptionクラス

ErrorExceptionクラス

コメント投稿(ログインが必要)



類似度ページランキング
順位 ページタイトル抜粋
1 set_error_handler 65
2 include_path 55
3 Generators 52
4 session_set_save_handler() 51
5 session_start() 50
6 register_globals 48
7 syntax error 48
8 ob_start 48
9 realpath 48
10 session_destroy関数 47
11 SessionHandler::gc 46
12 session_save_path() 44
13 preg_match 44
14 http_build_query 42
15 session.hash_function 42
16 register_shutdown_function 42
17 parse_url( ) 41
18 array_filter 41
19 session.gc_maxlifetime 41
20 foreach文 40
2024/4/24 13:05 更新
週間人気ページランキング / 4-17 → 4-23
順位 ページタイトル抜粋 アクセス数
1 ブラウザを閉じたらセッションデータはどうなるの? | セッション 16
2 Parse error: syntax error, unexpected 'public' (T_PUBLIC) | Parse error(エラーメッセージ) 13
3 curl で Cookie を使用する 8
3 PHPで定数を定義する方法は2種類ある / 配列定数の定義 8
4 Warning: strlen() expects parameter 1 to be string, array given in ○○.php on line △△ | Warning(エラーメッセージ) 6
5 コード例 … 「例外処理」はネストすることができる 5
5 or(||) | 演算子 5
6 php-devel とは? 4
6 Fatal error: Access level to ▲::$△ must be protected (as in class ●) or weaker | Fatal error(エラーメッセージ) 4
7 関数定義内での「外部ファイル読込」 | 制御構造 3
7 セッション管理が必要な理由は、HTTPプロトコルには状態を保持する機能がないため | セッション 3
7 PHP用語 3
7 ブラウザを閉じたらセッションデータはどうなるの? | セッション 3
7 Fatal error: Call to undefined method MDB2_Error::execute() in ○○ on line △△ | Fatal error(エラーメッセージ) 3
7 Fatal error: Uncaught Error: Class 'Mecab_Tagger' not found in /var/www/★★.php:☆☆ | Fatal error(エラーメッセージ) 3
7 Warning: include() [function.include]: Failed opening '**.php' for inclusion (in | Warning(エラーメッセージ) 3
7 Composer | 依存関係マネージャ 3
8 型の相互変換 | 型 2
8 インターフェイス | クラスとオブジェクト 2
8 クロスサイトスクリプティング | セキュリティ 2
2024/4/24 1:01 更新