1.PHP 中异常的独特性
PHP 中的异常的独特性, 即 PHP 中的异常不同于主流语言 C++java 中的异常在 Java 中, 异常是唯一的错误报告方式, 而在 PHP 中却不是这样, 而是把所有不正常的情况都视作了错误进行处理这两种语言对异常和错误的界定存在分歧什么是异常什么是错误, 两种语言的设计者存在不同的观点
PHP 中的异常:
是程序在运行中出现不符合预期的情况及与正常流程不同的状况一种不正常的情况, 按照正常逻辑本不该出的错误, 但仍然会出现的错误, 这是属于逻辑和业务流程的错误, 而不是编译或者语法上的错误
PHP 中的错误:
是属于 php 脚本自身的问题, 大部分情况是由错误的语法, 服务器环境导致, 使得编译器无法通过检查, 甚至无法运行的情况 warningnotice 都是错误, 只是他们的级别不同而已, 并且错误是不能被 try-catch 捕获的
在 PHP 中遇到任何自身错误都会触发一个错误, 而不是抛出异常 PHP 一旦遇到非正常代码, 通常都会触发错误, 而不是抛出异常因此, 如果想要使用异常处理不可预料的问题, 是办不到的
典型例子:
- <?php
- try {echo 1/0;} catch (Exception $e){
- echo $e->getMessage();
- }
结果:
结果显示:
此时出现了一个警告级别的错误, 程序终止
结论:
PHP 通常是无法自动捕获有意义的异常, 它把所有不正常的情况都视作了错误, 你要想捕获异常就得使用 if....else 结构, 保证代码是正常的, 然后判断进行手动抛出异常
2.PHP 中的错误级别
PHP 中的异常机制是不足的, 绝大多数情况下无法自动抛出异常, 必须使用 if....else 语句先进行判断, 在进行手动抛出异常
手动抛出异常的意义不大, 是已经预料到的错误, 这种方式将会使你陷入纷繁复杂的业务逻辑判断和处理中
因此我们可以通过一些特殊的函数来自定义错误处理函数, 来接管 PHP 原生的错误处理函数, 然后再进行抛出异常
接下来我们需要了解 PHP 中的一些错误
错误显示控制:
ALL 设置
全局: php.ini 中设置 display_error = on/off;
局部: ini_set("display_error", true/false);
PHP.ini 中 display_errors = Off 失效的解决
问题: PHP 设置文件 php.ini 中明明已经设置 display_errors = Off, 但是在运行过程中, 网页上还是会出现错误信息
解决: 经 查 log_errors= On, 据官方的说法, 当这个 log_errors 设置为 On, 那么必须指定 error_log 文件, 如果没指定或者指定的文件没有权限写入, 那么照样会输 出到正常的输出渠道, 那么也就使得 display_errors 这个指定的 Off 失效, 错误信息还是打印了出来于是将 log_errors = Off, 问题就解决了
选择性设置显示错误
全局: error_reporting = E_ALL | E_STRICT....
局部: error_reporting(E_ERROR | E_WARNING | E_PARSE)
1 E_ERROR 致命的运行错误错误无法恢复, 暂停执行脚本
2 E_WARNING 运行时警告 (非致命性错误) 非致命的运行错误, 脚本执行不会停止
4 E_PARSE 编译时解析错误解析错误只由分析器产生
8 E_NOTICE 运行时提醒(这些经常是你代码中的 bug 引起的, 也可能是有意的行为造成的)
16 E_CORE_ERROR PHP 启动时初始化过程中的致命错误
32 E_CORE_WARNING PHP 启动时初始化过程中的警告(非致命性错)
64 E_COMPILE_ERROR 编译时致命性错这就像由 Zend 脚本引擎生成了一个 E_ERROR
128 E_COMPILE_WARNING 编译时警告 (非致性错) 这就像由 Zend 脚本引擎生成了 E_WARNING 警告
256 E_USER_ERROR 自定义错误消息像用 PHP 函数 trigger_error(程序员设置 E_ERROR)
512 E_USER_WARNING 自定义警告消息像用 PHP 函数 trigger_error(程序员设的 E_WARNING 警告)
1024 E_USER_NOTICE 自定义的提醒消息像由使用 PHP 函数 trigger_error(程序员 E_NOTICE 集)
2048 E_STRICT 编码标准化警告允许 PHP 建议修改代码以确保最佳的互操作性向前兼容性
4096 E_RECOVERABLE_ERROR 开捕致命错误像 E_ERROR, 但可以通过用户定义的处理捕获(又见 set_error_handler())
8191 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
一共有十五种, 使用二进制代替, 0000 0000 0000 0011 表示 E_ERROR 和 E_WARNING
例如:
- error_reporting(3);// 只显示 E_ERROR 和 E_WARNING 错误
- error_reporting(-1);// 只显示所有错误误
注意:
在开发阶段通常是显示所有错误, 方便解决问题;
在生产阶段通常是隐藏错误, 并将需错误记录到文件中(错误日志);
php.ini 中设置: log_error = on/off;// 记录不记录
error_log = php_errors.log// 设定错误日志文件(此时没有给定路径则在当前位置生成)
还可以通过 ini_set()进行设置
3PHP 中的异常处理
3.1set_error_handler(error_function, error_type)
使用 set_error_handler(error_function, error_type)函数设置自定义错误处理函数, 接管原错误处理函数
- eg. < ?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 = 5 / 0;
- } catch(Exception $e) {
- echo "666666";
- }
访问结果:
由结果可知: 我们自定义的 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, 该函数只能捕获系统产生的一些 WarningNotice 级别的错误
注意:
如果在脚本执行前发生错误, 由于此时自定义的错误处理函数还没有注册, 因此就用不到这个自定义错误处理程序
3.2register_shutdown_function(exception_function)
捕获 PHP 的错误: Fatal ErrorParse Error 等, 这个方法是 PHP 脚本执行结束前最后一个调用的函数, 比如脚本错误 die()exit 异常正常结束都会调用
通过这个函数就可以在脚本结束前判断这次执行是否有错误产生, 这时就要借助于一个函数: error_get_last(); 这个函数可以拿到本次执行产生的所有错误 error_get_last(); 返回的信息:
[type] - 错误类型
[message] - 错误消息
[file] - 发生错误所在的文件
[line] - 发生错误所在的行
注意: 当 parse-time 出错时是不会调用本函数的只有在 run-time 出错的时候, 才会调用本函数即需要成功注册此函数才能使用测试 3 和测试 4 对比
- eg. < ?php
- try {
- $a = 5 / 0;
- } catch(Exception $e) {
- echo "666666";
- }
- register_shutdown_function('myshutdownfunc');
- function myshutdownfunc() {
- if ($error = error_get_last()) {
- echo "<pre>";
- print_r($error);
- echo "</pre>";
- die;
- }
- }
测试 1:
测试 2:(使用 echo "string"; 替换 try....catch)
测试 3:(使用 echo "string" 替换 try...catch)
此时语法错误, register_shutdown_function 函数未执行
测试 4:
新建一个文件, 具有语法错误的 php 代码, 并将其引入执行文件中, 例如
ceshi2.class.php 文件
- <?php
- echo "string"
- ?>
ceshi.class.php 文件
- <?php
- register_shutdown_function('myshutdownfunc');
- function myshutdownfunc()
- {
- if ($error = error_get_last()) {
- echo "<pre>";
- print_r($error);
- echo "</pre>";die;
- }
- }
- include "ceshi2.class.php";
- ?>
结果:
3.3set_exception_handler(exception_function)
参数 | 描述 |
---|---|
error_function | 必需。规定未捕获的异常发生时调用的函数。 该函数必须在调用 set_exception_handler() 函数之前定义。 这个异常处理函数需要需要一个参数,即抛出的 exception 对象。 |
作用:
set_exception_handler() 函数设置用户自定义的异常处理函数
该函数用于创建运行时期间的用户自己的异常处理方法
该函数会返回旧的异常处理程序, 若失败, 则返回 null
提示: 在这个异常处理程序被调用后, 脚本会停止执行
- eg. < ?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('Uncaught Exception occurred--- 没有人处理的异常');
运行结果:
来源: https://www.cnblogs.com/phpstudy2015-6/p/8433541.html