1、PHP中异常的独特性
PHP中的异常的独特性,即PHP中的异常不同于主流语言C++、java中的异常。在Java中,异常是唯一的错误报告方式,而在PHP中却不是这样,而是把所有不正常的情况都视作了错误进行处理。这两种语言对异常和错误的界定存在分歧。什么是异常什么是错误,两种语言的设计者存在不同的观点。
PHP中的异常:
是程序在运行中出现不符合预期的情况及与正常流程不同的状况。一种不正常的情况,按照正常逻辑本不该出的错误,但仍然会出现的错误,这是属于逻辑和业务流程的错误,而不是编译或者语法上的错误。
PHP中的错误:
是属于php脚本自身的问题,大部分情况是由错误的语法,服务器环境导致,使得编译器无法通过检查,甚至无法运行的情况。warning、notice都是错误,只是他们的级别不同而已,并且错误是不能被try-catch捕获的。
在PHP中遇到任何自身错误都会触发一个错误,而不是抛出异常。PHP一旦遇到非正常代码,通常都会触发错误,而不是抛出异常。因此,如果想要使用异常处理不可预料的问题,是办不到的。
典型例子:
<?php try { echo 1/0; } catch (Exception $e){ echo $e->getMessage(); }
输出:
Warning: Division by zero in D:\web\mytest\test.php on line 4
INF
结果显示:
此时出现了一个警告级别的错误,程序终止。
结论:
PHP通常是无法自动捕获有意义的异常,它把所有不正常的情况都视作了错误,你要想捕获异常就得使用if….else结构,保证代码是正常的,然后判断进行手动抛出异常。
E_ERROR 致命的运行错误。错误无法恢复,暂停执行脚本。 E_WARNING 运行时警告(非致命性错误)。非致命的运行错误,脚本执行不会停止。 E_PARSE 编译时解析错误。解析错误只由分析器产生。 E_NOTICE 运行时提醒(这些经常是你代码中的bug引起的,也可能是有意的行为造成的。) E_CORE_ERROR PHP 启动时初始化过程中的致命错误。 E_CORE_WARNING PHP启动时初始化过程中的警告(非致命性错)。 E_COMPILE_ERROR 编译时致命性错。这就像由Zend脚本引擎生成了一个E_ERROR。 E_COMPILE_WARNING 编译时警告(非致性错)。这就像由Zend脚本引擎生成了E_WARNING警告。 E_USER_ERROR 自定义错误消息。像用PHP函数trigger_error(程序员设置E_ERROR) E_USER_WARNING 自定义警告消息。像用PHP函数trigger_error(程序员设的E_WARNING警告) E_USER_NOTICE 自定义的提醒消息。像由使用PHP函数trigger_error(程序员E_NOTICE集) E_STRICT 编码标准化警告。允许PHP建议修改代码以确保最佳的互操作性向前兼容性。 E_RECOVERABLE_ERROR 开捕致命错误。像E_ERROR,但可以通过用户定义的处理捕获(又见set_error_handler()) E_ALL 所有的错误和警告(不包括 E_STRICT) (E_STRICT will be part of E_ALL as of PHP 6.0)14 16384 E_USER_DEPRECATED 15 30719 E_ALL
3.1、set_error_handler(error_function, error_type)
使用set_error_handler(error_function, error_type)函数设置自定义错误处理函数,接管原错误处理函数。
比如:
<?php // 方式一 // set_error_handler('myError'); // function myError($errorNum, $errorMs, $errorFile, $errorLine){ // echo('set_error_handler: ' . $errorNum . ':' . $errorMs . ' in ' . $errorFile . ' on ' . $errorLine . ' line '); // } // 方式二 class ErrorClass{ // 必须静态public方法 public static function myError($errorNum, $errorMs, $errorFile, $errorLine){ echo('set_error_handler: ' . $errorNum . ':' . $errorMs . ' in ' . $errorFile . ' on ' . $errorLine . ' line '); } } set_error_handler(['ErrorClass', 'myError']); try { $a = 1/0; } catch (Exception $e) { echo "666"; }
由结果可知:我们自定义的myError方法截取了错误,此时我们可以主动的处理这些错误,抛出相应的异常。
但是我们需要注意以下两点:
第一,如果存在该方法,相应的error_reporting()就不能在使用了。它将接管PHP原生错误处理函数,即所有的错误都会交给自定义的函数处理。
第二,此方法不能处理以下级别的错误:E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,set_error_handler() 函数所在文件中产生的E_STRICT,该函数只能捕获系统产生的一些Warning、Notice级别的错误。
注意:如果在脚本执行前发生错误,由于此时自定义的错误处理函数还没有注册,因此就用不到这个自定义错误处理程序。
捕获PHP的错误:Fatal Error、Parse Error等,这个方法是PHP脚本执行结束前最后一个调用的函数,比如脚本错误、die()、exit、异常、正常结束都会调用。
通过这个函数就可以在脚本结束前判断这次执行是否有错误产生,这时就要借助于一个函数:error_get_last();这个函数可以拿到本次执行产生的所有错误。error_get_last();返回的信息:
[type] – 错误类型
[message] – 错误消息
[file] – 发生错误所在的文件
[line] – 发生错误所在的行
注意:当parse-time出错时是不会调用本函数的。只有在run-time出错的时候,才会调用本函数。即需要成功注册此函数才能使用。【测试3和测试4对比】
<?php try { $a = 1/0; } catch (Exception $e) { echo "cat not divied by 0"; } register_shutdown_function('myshutdownfunc'); function myshutdownfunc() { if ($error = error_get_last()) { echo "<pre>"; print_r($error); echo "</pre>";die; } }
Warning: Division by zero in D:\web\mytest\test.php on line 4
Array ( [type] => 2 [message] => Division by zero [file] => D:\web\mytest\test.php [line] => 4 )<br data-filtered="filtered"><br data-filtered="filtered">
参数 | 描述 |
---|---|
error_function | 必需。规定未捕获的异常发生时调用的函数。 该函数必须在调用 set_exception_handler() 函数之前定义。 这个异常处理函数需要需要一个参数,即抛出的 exception 对象。 |
<?php // 第一种放方法 // function myException($exception) { // echo "<b>Exception:</b> " , $exception->getMessage(); // } // set_exception_handler('myException'); // 第二种方法 class MyError{ //必须是静态public方法 public static function myException($exception) { echo "<b>Exception:</b> " , $exception->getMessage(); } } set_exception_handler(['MyError', 'myException']); throw new Exception('没有人处理异常');