作为中国人开发的php框架。现已更新为tp6。但是随着tp6的到来,在底层上和tp5是不同的变化,我会继续分享框架的底层。
异常机制大家在项目都会使用到,但对于框架的异常原理你知道吗? 以及框架里面有错误但是它就是不抛出来,直接500服务错误。如何解决呢?
一、tp6异常有那些类型
tp6对php版本是7.1.0
因此,框架底部的异常捕获继承了throwable错误异常接口。所以整个框架都是基于这个接口进行操作的。有些朋友可能会说,exception不是用来捕捉一般异常的吗?为什么是throwable?
那是因为exception类是实现了throwable接口,从而来方面我们调用。接口如果不实现它有用吗?实现流程:tp框架的exception类继承php底层exception类,底层类再去实现throwable接口
tp6共有8种异常类型,都在vendor\topthink\framework\src\think\exception下面:
它们是:错误异常、文件异常、系统异常、http异常、http响应异常、违规数据异常、路由异常和数据验证异常
errorexception是一个错误异常,这就是为什么像php这样的语法错误框架可以捕捉到它。
而大家常用的异常类抛出异常,它会实现php底层的errorexception类,而且像errorexception也会实现exception基类。所以大家可以把它理解为应用逻辑操纵的基类。,像http、route、valide一样,将继承php底部的runtimeexception
runtimeexception仍将继承exception
runtimeexception类的继承模式
常用的方法如getmessage和getfile都是从我们的throwable接口派生出来的
二、异常捕获的原理解析
tp6框架允许2中方式,分为手动与自动捕获。手动捕获异常,这是基于try-catch结构的。例如:
尝试{
回声44;
抛出新的exception("我手动抛出");
}捕获(\异常$e) {
//这是异常捕获
返回json($ e-getmessage());
}
//执行结果:44‘我手动扔出去的’
注意:php异常是不抛出不执行的,这里的手动抛出是指,当我们throw抛出后。它会在下面的catch里面进行捕获。而不是说你都不 throw new exception对象。就可以在下面捕获到异常
抛出一个异常就是执行tp定义的异常类,也就是我们框架目录下的vendor\topthink\framework\src\think\exception.php类
那自动是怎么实现的呢?
自动实现是我们再去启动框架的时候会把它自动的注入到容器里面并绑定关系的。一开始是没有,当运行后就会绑定起来。
绑定后,array_merge就是把多个数组合并成一个。如果有多种关系,就用一种结合绑定。最后是think \ exception \ handle=app \ exception handle的关系
这就是为什么tp6默认实现了它的全局自动异常类,所以你不必实现它。而这个实现的类就是app\exceptionhandle类库。也就是说,框架中绑定的服务实例会在框架加载时启动。
那这个自动方式 也需要调用方法啊?你不调用怎么执行呢?
当我们绑定实例化关系,然后将实例绑定到容器时,我们将执行http请求,该请求位于http之下以捕获我们的异常。
看到了吗?当我们执行该请求时,如果抛出异常,它将被throwable接口管理到。接口触及
实现接口的是类库,很好理解。然后我们将调用先前在容器中注册的handle::class—report()方法
三、框架应用错误不抛出的解决方案
之所以不抛出框架应用的错误,是因为框架默认只捕获http请求的处理,不影响应用。所以如果你的申请有问题,它不能被赶出,这个大家后面写代码的时候一定要去注意到,不然到时候就尴尬了
例如:配置文件log.php有语法错误,但是你去访问方法的时候就直接报500,而不是抛出异常,如果你的应用配置接口不对也是一样的
那怎么会这样呢?
这是因为当我们执行自动抛出的请求时,我们需要反转容器中的实例。当我们的错误被错误地应用时,我们将在error,的错误注册机制中捕获它,该机制不是常见的错误异常捕获机制。而在应用错误捕获,我们是把错误信息打印到控制台上,所以它不会输出到我们浏览器上面
如何解决:大家可以用debug来调试下,就可以看到他直接打印到控制台上