ホームページ  >  記事  >  バックエンド開発  >  PHP7 が set_error_handler と set_Exception_handler を使用して例外メカニズムを処理する方法

PHP7 が set_error_handler と set_Exception_handler を使用して例外メカニズムを処理する方法

醉折花枝作酒筹
醉折花枝作酒筹転載
2021-05-31 09:17:252328ブラウズ

この記事では、PHP7 が set_error_handler と set_Exception_handler を使用して例外メカニズムを処理する方法を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

PHP7 が set_error_handler と set_Exception_handler を使用して例外メカニズムを処理する方法

歴史的な理由により、PHP は元々プロセス指向言語として設計されたため、例外処理では Java のような try/catch メカニズムが使用されず、エラーが直接表示されます。 PHP エラーは、E_ERROR、E_WARNING、E_PARSE、E_NOTICE などの多くのレベルに分類されます。E_ERROR、E_PARSE のような重大なエラーの場合、PHP はページを直接終了します。操作のスクリプト。

php5 バージョンでは、set_error_handler を使用して、PHP の標準エラー処理メソッド (ページへの出力またはログへの記録) の代わりに独自のエラー処理メソッドを登録できますが、一部の重大なエラーは php5 バージョンでは処理できません。これに対処するために、マニュアルのこのメソッドの紹介を見てみましょう:

mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )

设置一个用户的函数(error_handler)来处理脚本中出现的错误。 

本函数可以用你自己定义的方式来处理运行中的错误, 例如,在应用程序中严重错误发生时,或者在特定条件下触发了一个错误(使用 trigger_error()),你需要对数据/文件做清理回收。 

重要的是要记住 error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序, 除非回调函数返回了 FALSE。 error_reporting() 设置将不会起到作用而你的错误处理函数继续会被调用 —— 不过你仍然可以获取 error_reporting 的当前值,并做适当处理。 需要特别注意的是带 @ error-control operator 前缀的语句发生错误时,这个值会是 0。 

同时注意,在需要时你有责任使用 die()。 如果错误处理程序返回了,脚本将会继续执行发生错误的后一行。 

以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。

マニュアルには、E_ERROR や E_PARSE などのエラーはユーザーが処理できないことが明確に記載されています。コードのデモ(以下) サンプルはphp5.6で実行しています)

<?php
 
//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}
 
set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误
 
 
echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

実行結果:

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: D:\project\demo\demo.php
出错行号errline: 16

このとき、通常のようにエラーメッセージはページに直接出力されませんが、 set_error_handler 関数を使用しない場合は、このようにエラーメッセージが表示されますが、PHP のエラー表示をオフにして、エラーがページに直接表示されないようにすることもできます。

Notice: Undefined variable: foo in D:\project\demo\demo.php on line 15

この処理メカニズムは非常に優れているように見えますが、前述したように、すべてのエラーをこの方法で処理できるわけではありません。上記のコードを次のように変更します:

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误

もう一度実行:

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: D:\project\demo\demo.php
出错行号errline: 15
错误编号errno: 256
错误信息errstr: 人为产生触发一个错误
出错文件errfile: D:\project\demo\demo.php
出错行号errline: 17

Fatal error: Call to undefined function foobar() in D:\project\demo\demo.php on line 19

予想どおり、最初の 2 つのエラーは「捕捉」され、処理されましたが、最後の致命的エラーは登録したエラー関数に従って処理されず、デフォルトの処理方法が引き続き使用されました。これも、 php5 バージョンの取り扱いに大きな欠陥があります。 PHP7 以降、例外処理メソッドにはいくつかの新しい変更があります。マニュアルの導入部分を見てみましょう:

PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error 异常抛出。 

这种 Error 异常可以像 Exception 异常一样被第一个匹配的 try / catch 块所捕获。如果没有匹配的 catch 块,则调用异常处理函数(事先通过 set_exception_handler() 注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。 

Error 类并非继承自 Exception 类,所以不能用 catch (Exception $e) { ... } 来捕获 Error。你可以用 catch (Error $e) { ... },或者通过注册异常处理函数( set_exception_handler())来捕获 Error。

PHP7 のこのエラー処理メカニズムは、Java を学習するようなもので、大規模なエラー処理を処理できるようになります。ほとんどの例外については、以下のコード例を参照してください (次のコードは php7 を使用して実行されます)

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


try
{
    echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

    trigger_error(&#39;人为产生触发一个错误&#39;, E_USER_ERROR); //人为触发错误

    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
}
catch (Error $e)
{
    echo "Error code: " . $e->getCode() . &#39;<br>&#39;;
    echo "Error message: " . $e->getMessage() . &#39;<br>&#39;;
    echo "Error file: " . $e->getFile() . &#39;<br>&#39;;
    echo "Error fileline: " . $e->getLine() . &#39;<br>&#39;;
}

実行結果:

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 17
错误编号errno: 256
错误信息errstr: 人为产生触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 19
Error code: 0
Error message: Call to undefined function foobar()
Error file: E:\project\demo\demo.php
Error fileline: 21

このようにして、さまざまな種類のエラーを次の方法で処理できます。致命的なエラーも含めて。 try / catch が使用されない場合、php7 のエラー メッセージは php5 のエラー メッセージとは多少異なります。

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 17
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 19

Fatal error: Uncaught Error: Call to undefined function foobar() in E:\project\demo\demo.php:21 Stack trace: #0 {main} thrown in E:\project\demo\demo.php on line 21

致命的エラーの説明は次のようになります。スローされたエラーはキャッチされませんでした。

ここでのキャッチは、Error クラスのエラーのみのキャッチに限定されており、マニュアルには、Error クラスは Exception クラスのサブクラスではないことが明確に記載されていることに注意してください。コードを同時に実行します。不可能ではありませんか? コードを見てください:

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


try
{
    echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

    trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

    throw new Exception(&#39;This is a exception&#39;, 400);  //抛出一个Exception,看是否可以被catch

    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
}
catch (Error $e)
{
    echo "Error code: " . $e->getCode() . &#39;<br>&#39;;
    echo "Error message: " . $e->getMessage() . &#39;<br>&#39;;
    echo "Error file: " . $e->getFile() . &#39;<br>&#39;;
    echo "Error fileline: " . $e->getLine() . &#39;<br>&#39;;
}

実行結果:

错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 17
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 19

Fatal error: Uncaught Exception: This is a exception in E:\project\demo\demo.php:21 Stack trace: #0 {main} thrown in E:\project\demo\demo.php on line 21

何か方法はありますか? 実際、次の継承図を見てください。マニュアル


Error クラスと Exception クラスは両方とも Throwable のサブクラスであることがわかります (実際には、Error クラスと Exception クラスは両方とも Throwable インターフェイスを実装しています) ) なので、上記のコードは次のように最適化できます。

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误


try
{
    echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

    trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

    if (mt_rand(1, 10) > 5)
    {
        throw new Exception(&#39;This is a exception&#39;, 400);  //抛出一个Exception,看是否可以被catch
    }
    else
    {
        foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
    }
}
catch (Throwable $e)
{
    echo "Error code: " . $e->getCode() . &#39;<br>&#39;;
    echo "Error message: " . $e->getMessage() . &#39;<br>&#39;;
    echo "Error file: " . $e->getFile() . &#39;<br>&#39;;
    echo "Error fileline: " . $e->getLine() . &#39;<br>&#39;;
}

例外かエラーかに関係なく、複数回実行すると、キャプチャして処理できることがわかります。

すべてのエラーを try/catch で処理したくない場合は、set_Exception_handler を使用して例外処理関数を登録することもできます。この方法では、キャッチされない例外が発生したときに、システムが自動的に私たちがそれを処理するために登録されたハンドラー関数。

<?php

//自定义的错误处理方法
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    echo "错误编号errno: $errno<br>";
    echo "错误信息errstr: $errstr<br>";
    echo "出错文件errfile: $errfile<br>";
    echo "出错行号errline: $errline<br>";
}

set_error_handler(&#39;_error_handler&#39;, E_ALL | E_STRICT);  // 注册错误处理方法来处理所有错误

function _exception_handler(Throwable $e)
{
    if ($e instanceof Error)
    {
        echo "catch Error: " . $e->getCode() . &#39;   &#39; . $e->getMessage() . &#39;<br>&#39;;
    }
    else
    {
        echo "catch Exception: " . $e->getCode() . &#39;   &#39; . $e->getMessage() . &#39;<br>&#39;;
    }
}

set_exception_handler(&#39;_exception_handler&#39;);    // 注册异常处理方法来捕获异常


echo $foo[&#39;bar&#39;];  // 由于数组未定义,会产生一个notice级别的错误

trigger_error(&#39;人为触发一个错误&#39;, E_USER_ERROR); //人为触发错误

if (mt_rand(1, 10) > 5)
{
    throw new Exception(&#39;This is a exception&#39;, 400);  //抛出一个Exception,看是否可以被catch
}
else
{
    foobar(3, 5);   //调用未定义的方法将会产生一个Error级别的错误
}
错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 29
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 31
catch Error: 0 Call to undefined function foobar()


错误编号errno: 8
错误信息errstr: Undefined variable: foo
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 29
错误编号errno: 256
错误信息errstr: 人为触发一个错误
出错文件errfile: E:\project\demo\demo.php
出错行号errline: 31
catch Exception: 400 This is a exception

現時点では、PHP7 でまた混乱するかもしれません。どれが set_error_handler で処理され、どれが set_Exception_handler で処理されます。マニュアルにはこれについて明確に説明されていません。私の要約によると、一般的には問題は発生しません。スクリプトを終了します。エラーは set_error_handler によって処理され、スクリプトの実行を終了させる重大なエラーはエラーとしてスローされますが、絶対的なものではありません。上記で人為的にトリガーされた

E_USER_ERROR は、スクリプトの実行を中断するエラーです。スクリプトを実行しても実行されない Error 例外としてスローされず、set_error_handler で登録されたメソッドによって処理される これは、この種のエラーが人為的に生成されているため、PHP7 のエラー処理がまだ残っているためと考えられますやや曖昧であり、私たち自身で扱うには適していませんので、ご注意ください。

推奨学習: php ビデオ チュートリアル

以上がPHP7 が set_error_handler と set_Exception_handler を使用して例外メカニズムを処理する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。