您现在的位置是:群英 > 开发技术 > PHP语言
PHP错误与异常处理怎么办,怎么理解
Admin发表于 2022-05-11 12:02:41817 次浏览
在实际案例的操作过程中,我们可能会遇到“PHP错误与异常处理怎么办,怎么理解”这样的问题,那么我们该如何处理和解决这样的情况呢?这篇小编就给大家总结了一些方法,具有一定的借鉴价值,希望对大家有所帮助,接下来就让小编带领大家一起了解看看吧。

目录
  • 一、异常与错误的概述
    • PHP中什么是异常
    • PHP中什么是错误
    • 上面的说法是有前提条件的
    • PHP异常处理很鸡肋?
  • 二、ERROR的级别
  • 三、PHP异常处理中的黑科技
    • 1:set_error_handler()
    • 2:register_shutdown_function()
    • 3:set_exception_handler()
  • 四、巧妙的捕获错误和异常
    • 1:把错误以异常的形式抛出(不能完全抛出)
    • 2:捕获所有的错误
  • 五、自定义异常处理和异常嵌套
    • 1:自定义异常处理
    • 2:异常嵌套
  • 六、PHP7中的异常处理

请一定要注意,没有特殊说明:本例 PHP Version < 7
说起PHP异常处理,大家首先会想到try-catch,那好,我们先看一段程序吧:有一个test.php文件,有一段简单的PHP程序,内容如下,然后命令行执行:php test.php

getMessage();
	}
?>

我的问题是:这段程序能正确的捕捉到除0的错误信息吗?

如果你回答能,那你就把这篇文章看完吧!应该能学点东西。

本文章分5个部分介绍我的异常处理的理解:

一、异常与错误的概述

PHP中什么是异常

程序在运行中出现不符合预期的情况,允许发生(你也不想让他出现不正常的情况)但他是一种不正常的情况,按照我们的正常逻辑本不该出的错误,但仍然会出现的错误,属于逻辑和业务流程的错误,而不是编译或者语法上的错误。

PHP中什么是错误

属于php脚本自身的问题,大部分情况是由错误的语法,服务器环境导致,使得编译器无法通过检查,甚至无法运行的情况。warning、notice都是错误,只是他们的级别不同而已,并且错误是不能被try-catch捕获的。

上面的说法是有前提条件的

在PHP中,因为在其他语言中就不能这样下结论了,也就是说异常和错误的说法在不同的语言有不同的说法。在PHP中任何自身的错误或者是非正常的代码都会当做错误对待,并不会以异常的形式抛出,但是也有一些情况会当做异常和错误同时抛出(据说是,我没有找到合适的例子)。也就是说,你想在数据库连接失败的时候自动捕获异常是行不通的,因为这就不是异常,是错误。但是在java中就不一样了,他会把很多和预期不一致的行为当做异常来进行捕获。

PHP异常处理很鸡肋?

在上面的分析中我们可以看出,PHP并不能主动的抛出异常,但是你可以手动抛出异常,这就很无语了,如果你知道哪里会出问题,你添加if else解决不就行了吗,为啥还要手动抛出异常,既然能手动抛出就证明这个不是异常,而是意料之中。以我的理解,这就是PHP异常处理鸡肋的地方(不一定对啊)。所以PHP的异常机制不是那么的完美,但是使用过框架的同学都知道有这个情况:你在框架中直接写开头那段php“自动”捕获异常的代码是可以的,这是为什么?看过源码的同学都知道框架中都会涉及三个函数:register_shutdown_function,set_error_handler,set_exception_handler后面我会重点讲解着三个黑科技,通过这几个函数我们可以实现PHP假自动捕获异常和错误。

二、ERROR的级别

只有熟悉错误级别才能对错误捕捉有更好的认识。 ERROR有不同的错误级别,我之前的一篇文章中有写到:http://www.cnblogs.com/zyf-zhaoyafei/p/3649434.html
下面我再总结性的给出这几类错误级别:

Fatal Error:致命错误(脚本终止运行)
        E_ERROR         // 致命的运行错误,错误无法恢复,暂停执行脚本
        E_CORE_ERROR    // PHP启动时初始化过程中的致命错误
        E_COMPILE_ERROR // 编译时致命性错,就像由Zend脚本引擎生成了一个E_ERROR
        E_USER_ERROR    // 自定义错误消息。像用PHP函数trigger_error(错误类型设置为:E_USER_ERROR)

    Parse Error:编译时解析错误,语法错误(脚本终止运行)
        E_PARSE  //编译时的语法解析错误

    Warning Error:警告错误(仅给出提示信息,脚本不终止运行)
        E_WARNING         // 运行时警告 (非致命错误)。
        E_CORE_WARNING    // PHP初始化启动过程中发生的警告 (非致命错误) 。
        E_COMPILE_WARNING // 编译警告
        E_USER_WARNING    // 用户产生的警告信息

    Notice Error:通知错误(仅给出通知信息,脚本不终止运行)
        E_NOTICE      // 运行时通知。表示脚本遇到可能会表现为错误的情况.
        E_USER_NOTICE // 用户产生的通知信息。

由此可知有5类是产生ERROR级别的错误,这种错误直接导致PHP程序退出。
可以定义成:

1 ERROR = E_ERROR | E_CORE_ERROR |  E_COMPILE_ERROR | E_USER_ERROR | E_PARSE

三、PHP异常处理中的黑科技

前面提到框架中是可以捕获所有的错误和异常的,之所以能实现应该是使用了黑科技,哈哈!其实也不是什么黑科技,主要是三个重要的函数:

1:set_error_handler()

看到这个名字估计就知道什么意思了,这个函数用于捕获错误,设置一个用户自定义的错误处理函数。

2:register_shutdown_function()

捕获PHP的错误:Fatal Error、Parse Error等,这个方法是PHP脚本执行结束前最后一个调用的函数,比如脚本错误、die()、exit、异常、正常结束都会调用,多么牛逼的一个函数啊!通过这个函数就可以在脚本结束前判断这次执行是否有错误产生,这时就要借助于一个函数:error_get_last();这个函数可以拿到本次执行产生的所有错误。error_get_last();返回的信息:
[type] - 错误类型
[message] - 错误消息
[file] - 发生错误所在的文件
[line] - 发生错误所在的行

由此引出一个奇葩的问题:问什么不能触发,为什么框架中是可以的?其实原因很简单,只在parse-time出错时是不会调用本函数的。只有在run-time出错的时候,才会调用本函数,我的理解是语法检查器前没有执行register_shutdown_function()去把需要注册的函数放到调用的堆栈中,所以就根本不会运行。那框架中为什么任何错误都能进入到register_shutdown_function()中呢,其实在框架中一般会有统一的入口index.php,然后每个类库文件都会通过include ** 的方式加载到index.php中,相当与所有的程序都会在index.php中聚集,同样,你写的具有语法错误的文件也会被引入到入口文件中,这样的话,调用框架,执行index.php,index.php本身并没有语法错误,也就不会产生parse-time错误,而是 include 文件出错了,是run-time的时候出错了,所以框架执行完之后就会触发register_shutdown_function();
所以现在可是试一下这个写法,这样就会触发zyfshutdownfunc()回调了:

a.php文件


b.php文件
getMessage();
    }
?>

好了,试一下,会打印出:

Division by zero zyf123

流程:本来是除0错误,然后触发set_error_handler(),在set_error_handler()中相当与杀了个回马枪,再把错误信息以异常的形式抛出来,这样就可以实现错误以异常的形式抛出。大家要注意:这样做是有缺点的,会受到set_error_handler()函数捕获级别的限制。

2:捕获所有的错误

由set_error_handler()可知,他能够捕获一部分错误,不能捕获系统级E_ERROR、E_PARSE等错误,但是这部分可以由register_shutdown_function()捕获。所以两者结合能出现很好的功能。
看下面的程序:

a.php内容:

b.php内容:
getLine().' in ' . $this->getFile()
                .': ' . $this->getMessage() . ' Must in (0 - 60)';
        }
    }

    $age = 10;
    try {
        $age = intval($age);
        if($age > 60) {
            throw new zyfException($age);
        }

    } catch (zyfException $e) {
        echo $e->errorzyfMessage();

    }
?>

2:异常嵌套

异常嵌套是比较常见的写法,在自定义的异常处理中,try 块中可以定义多个异常捕获,然后分层传递异常,理解和冒泡差不多,看下面的实现:

 60) {
            throw new zyfException($age);
        }

        if ($age <= 0) { throw new Exception($age . ' must > 0');
        }

    } catch (zyfException $e) {
        echo $e->errorzyfMessage();

    } catch(Exception $e) {
        echo $e->getMessage();
    }
?>

当然也可以在catch中再抛出异常给上层:

 60) {
                throw new Exception($age);
            }

        } catch (Exception $e) {
            throw new zyfException($age);

        }

    } catch (zyfException $e) {
        echo $e->errorzyfMessage();
    }
?>

六、PHP7中的异常处理

现在写PHP必须考虑版本情况,上面的写法在PHP7中大部分都能实现,但是也会有不同点,在PHP7更新中有一条:更多的Error变为可捕获的Exception,现在的PHP7实现了一个全局的throwable接口,原来老的Exception和其中一部分Error实现了这个接口(interface),PHP7中更多的Error变为可捕获的Exception返回给捕捉器,这样其实和前面提到的扩展try-catch影响范围一样,但是如果不捕获则还是按照Error对待,看下面两个:

getMessage() . ' zyf';
    }

    try {
        test();

    } catch(Error $e) {
        echo $e->getMessage() . ' zyf';
    }
?>

因为PHP7实现了throwable接口,那么就可以使用第一个这种方式来捕获异常。又因为部分Error实现了接口,并且更多的Error变为可捕获的Exception,那么就可以使用第二种方式来捕获异常。下面是在网上找的PHP7的异常层次树:
Throwable
Exception 异常
...
Error 错误
ArithmeticError 算数错误
DivisionByZeroError 除数为0的错误
AssertionError 声明错误
ParseError 解析错误
TypeError 类型错误



感谢各位的阅读,以上就是“PHP错误与异常处理怎么办,怎么理解”的内容了,通过以上内容的阐述,相信大家对PHP错误与异常处理怎么办,怎么理解已经有了进一步的了解,如果想要了解更多相关的内容,欢迎关注群英网络,群英网络将为大家推送更多相关知识点的文章。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: PHP异常与错误
相关信息推荐
2022-05-12 11:16:07 
摘要:这篇文章主要介绍了PHP代码加密和扩展解密实战,对加密解密感兴趣的同学,可以参考下
2022-07-30 17:34:48 
摘要:socketio必须用在node中;socketio是nodejs的一个库,利用nodejs的函数封装了一些功能,并且依赖于nodejs的一些api,所以只能在nodejs中使用,socketio也是在客户端和服务端之间建立的双向通信数据交换技术,底层使用EngineIO。
2021-12-01 19:07:28 
摘要:这篇文章给大家分享的是PHP中imagettftext()函数的使用。小编觉得挺实用的,因此分享给大家做个参考,文中示例代码介绍的非常详细,感兴趣的朋友接下来一起跟随小编看看吧。
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部