PHP の「エラー処理ハンドラ」「シャットダウンハンドラ」「例外処理ハンドラ」の挙動「建议收藏」

PHP の「エラー処理ハンドラ」「シャットダウンハンドラ」「例外処理ハンドラ」の挙動「建议收藏」エラーレポートレベルの指定PHPには様々なレベルのエラーが定義されています

PHP

エラーレポートレベルの指定

PHP には様々なレベルのエラーが定義されています。

定数
1 E_ERROR
2 E_WARNING
4 E_PARSE
8 E_NOTICE
16 E_CORE_ERROR
32 E_CORE_WARNING
64 E_COMPILE_ERROR
128 E_COMPILE_WARNING
256 E_USER_ERROR
512 E_USER_WARNING
1024 E_USER_NOTICE
2048 E_STRICT
4096 E_RECOVERABLE_ERROR
8192 E_DEPRECATED
16384 E_USER_DEPRECATED
(PHP バージョンに依存) E_ALL

error_reporting 関数に上記の定数を渡すことで、どのレベルのエラーをレポートすべきか PHP に指示することができます。

全てのエラーをレポートするには、E_ALL を指定します。PHP4 と PHP5 では既定では E_ALL & ~E_NOTICE が指定されます。

エラーハンドラの指定

エラーハンドラは、set_error_handler 関数で指定します。

次の例では $i = 5/0; の行で 0 除算の警告が発生しますが、その箇所でユーザー定義の エラーハンドラである my_error_handler 関数が呼ばれます。

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

function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
  
  
     echo "[$errno] $errstr $errfile($errline)\n";
}
?>
> php error2.php
[2] Division by zero C:\Temp\error2.php(3)

>

Fatal Error の処理 ~ スクリプトのシャットダウン関数を利用

ただし、次のタイプのエラーはこのユーザー定義のエラーハンドラで処理できない、と PHP のサイトに書いてあります。

  • E_ERROR
  • E_PARSE
  • E_CORE_ERROR
  • E_CORE_WARNING
  • E_COMPILE_ERROR
  • E_COMPILE_WARNING

試しに、次のように未定義の関数 foo() を呼び出してみます。

<?php
set_error_handler( 'my_error_handler', E_ALL );

$i = 5/0;
foo();

function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
  
  
     echo "[$errno] $errstr $errfile($errline)\n";
}
?>

すると、次のように警告はユーザー定義のエラーハンドラで処理されていることがわかりますが、 肝心の Fatal Error が処理されません。

> php error2.php
[2] Division by zero C:\Temp\error2.php(4)

Fatal error: Call to undefined function foo() in C:\Temp\error2.php on line 5

>

これは Fatal error (致命的エラー) の箇所で、既にスクリプトの修了処理が始まってしまい、ユーザー定義のエラーハンドラ関数が呼び出されないため、 と考えられます。

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

<?php
ini_set( 'display_errors' , 0 );
error_reporting( E_ALL );
set_error_handler( 'my_error_handler', E_ALL );
register_shutdown_function( 'my_shutdown_handler' );

echo "Hello\n";
$i = 5/0;
foo();
echo "Bye\n";


function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
  
  
     echo "[$errno] $errstr $errfile($errline)\n";
}

function my_shutdown_handler(){
  
  
     $isError = false;
     if ($error = error_get_last()){
  
  
          switch($error['type']){
  
  
          case E_ERROR:
          case E_PARSE:
          case E_CORE_ERROR:
          case E_CORE_WARNING:
          case E_COMPILE_ERROR:
          case E_COMPILE_WARNING:
               $isError = true;
                      break;
              }
         }
     if ($isError){
  
  
          echo my_error_handler( 
               $error['type'], 
               $error['message'], 
               $error['file'], 
               $error['line'], 
               null );
     }
}
?>

この実行結果は次のようになります。

> php error3.php
Hello
[2] Division by zero C:\Temp\error3.php(10)
[1] Call to undefined function foo() C:\Temp\error3.php(11)

“Bye” という文字を出力する行へ復帰は出来ませんが、シャットダウン関数からエラーハンドラを呼びだせています。

致命的なエラーだが、復帰できる場合

それでは Fatal エラーは常に復帰できないか、というと実はそうでもなく、try-catch で例外をキャッチすることで、 プログラムの実行を継続することが可能な場合もあります。

次の例を見てください。

<?php
set_error_handler( 'my_error_handler', E_ALL );

echo "Hello!\n";
$x = new COM('AAA.BBB');
echo "Bye!\n";

function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
  
  
     echo "[$errno] $errstr $errfile($errline)\n";
}
?>

このコードでは new COM(‘AAA.BBB’) という箇所で、デタラメなプログラム識別子を渡して処理を失敗させています。

これを実行すると、次の結果となります。

>php error4.php
Hello!

Fatal error: Uncaught exception 'com_exception' with message 
'Failed to create COM object `AAA.BBB': Invalid syntax' in C:\Temp\error4.php:5
Stack trace:
#0 C:\Temp\error4.php(5): com->com('AAA.BBB')
#1 {main}
  thrown in C:\Temp\error4.php on line 5

エラーハンドラをセットしているにもかかわらず、エラーハンドラに入りません。

エラーメッセージを見ると、例外が発生していることがわかりますので、 次のように try-catch で例外を捕捉します。

<?php
set_error_handler( 'my_error_handler', E_ALL );

echo "Hello!\n";

try {
  
  
     $x = new COM('AAA.BBB');
}
catch( Exception $e ) {
  
  
     echo $e->getMessage();
}

echo "Bye!\n";

function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
  
  
     echo "[$errno] $errstr $errfile($errline)\n";
}
?>

これによって、次のような実行結果を得ました。

>php error4.php
Hello!
Failed to create COM object `AAA.BBB': Invalid syntax
Bye!

確かに Bye! という文字が表示されており、スクリプトの処理が継続されていることがわかります。

エラーハンドラと同様な構文の set_exception_handler 関数がありますので、これが利用できないか検討するため、 set_exception_handler 関数でデフォルトの例外処理ハンドラをセットすると次のようになります。

<?php
set_error_handler( 'my_error_handler', E_ALL );
set_exception_handler( 'my_exception_handler' );

echo "Hello!\n";
$x = new COM('AAA.BBB');
echo "Bye!\n";

function my_error_handler ( $errno, $errstr, $errfile, $errline, $errcontext ) {
  
  
     echo "[$errno] $errstr $errfile($errline)\n";
}

function my_exception_handler ( $e ) {
  
  
     echo $e->getMessage() . ' ' . $e->getFile() . '(' . $e->getLine() . ")\n";
}
?>

実行結果は次の通りです。

> php error4.php
Hello!
Failed to create COM object `AAA.BBB': Invalid syntax
 C:\Temp\error4.php(6)

確かに例外処理ハンドラが呼び出されていることはわかりますが、処理は元の場所へ復帰するわけではなく、 そこで終了します。

今天的文章PHP の「エラー処理ハンドラ」「シャットダウンハンドラ」「例外処理ハンドラ」の挙動「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/87012.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注