使用 Symfony 组件创建自己的 PHP 框架(第十一部分:HttpKernel 组件以及使用事件处理异常)

使用 Symfony 组件创建自己的 PHP 框架(第十一部分:HttpKernel 组件以及使用事件处理异常)

Chris Yue 7 comments
Posts

英文原文地址:https://symfony.com/doc/current/create_framework/http_kernel_httpkernel_class.html

如果你正在使用我们的框架,你或许想让框架支持自定义错误页面。目前,我们可以处理 404 和 500 错误,不过此功能都是硬编码在框架里面的。但让错误信息变得可自定义也非常容易:分发一个新事件然后监听它。要做到这点也就意味着监听器(listener)需要调用一个控制器。

但要是这个控制器也抛异常,那不是会发生无限循环调用?应该有更方便的方法是吧。

下面看看 HttpKernel 类。HttpKernel 类是对 HttpKernelInterface 接口的一个可被广泛使用的,灵活的,可扩展的实现。我们就是用它而不用反反复复的发明轮子(译者注:又来了作者真讨厌发明轮子)。

这个类跟我们目前写的类非常的类似:它在一个请求进来的时候,在某些策略点(strategic point)分发事件,并使用控制器分析器来选择某一个控制器去处理请求。它会非常的细心处理各种问题,并且在有问题发生的时候,会有非常棒的回馈。

下面是我们的新框架代码:

以及新版控制器:

RouterListener 是一个跟我们之前实现的一样逻辑的类:匹配请求的路由,并且根据路由参数为请求生成更多的属性。

现在我们的代码既精简,功能又强大,比以前更加的给力了。比如说现在可以利用 ExceptionListener 监听器来让你的错误处理变得能够配置。

ExceptionListener 使用 FlattenException 来代替抛出 Exception,让你更加容易地操作和显示异常。它能使用任何有效的控制器作为异常的处理器,所以你可以建立一个错误控制器(ErrorController 类)来代替闭包

错误控制器代码如下:

怎样?轻易得得到一个简洁而又可自定义的错误管理功能!如果你的控制器抛出一个异常,HttpKernel 会很好去处理它。

在第二章,我们曾经聊过 Response::prepare() 这个方法,此方法能保证响应是严格遵守http协议的.如果能在响应客户端之前,都调用一次这个方法,那有多好。其实这便是 ResponseListener 所做的事情:

是不是很方便呢?让我们再添加一个新功能,让响应对象支持响应流(streamed response)功能如何?只用注册一个 StreamedResponseListener 就行了:

然后在你的控制器里返回一个 StreamedResponse 实例来替代以前的 Response 实例

请阅读 Symfony 组件的 Internal 这一章,了解更多利用 HttpKernel 做事件分发的知识点,以及他们是如何改变对请求的处理流程的

现在让我们在添加一个可以允许控制器仅返回字符串,而非必须返回一个完整的响应对象的监听器:

为了实现此功能,我们需要监听内核里面的 kernel.view 事件,此事件会在控制器刚被调用结束后触发。它的作用是仅在需要的时候,将控制器返回的字符串转化成一个完全的响应对象:

只有当控制器返回不是响应对象的时候,此事件才会被触发,另外如果在此事件上设置了响应对象,便停止了此事件的继续传播(原文还有一句,说正因为如此所以代码很简单,但是我觉得这代码简不简单没什么直接逻辑,不知道作者什么意思)

当然别忘记在前端控制器里面注册它

如果你忘记了注册(译者注:StringResponseListener),HttpKernel 会抛出一个带有很好错误提示的异常:The controller must return a response (Nope, this is not a leap year. given)..

至此,我们的框架代码是越来越紧凑,而且都是用现成的库组成的。扩展的本质其实就是事件监听+订阅事件。

但愿你现在能够理解为什么这看起来那么简单的 HttpKernelInterface 会这么的强大。它默认实现 HttpKernel,能让你感受到很多的很酷的特性,而且能毫不费劲得使用它。又因为 HttpKernel 是 Symfony 以及 Silex 框架的核心,所以你可以有两全其美的选择:在一个稳固的,持续维护的,并且在许多网站都已验证的地基架构上,做一个可定制的,满足你需求的框架,以及写出做过安全审计而又能很好扩展的代码。

返回阅读第十部分 | 继续阅读第十二部分

使用 Symfony 组件创建自己的 PHP 框架(第十一部分:HttpKernel 组件以及使用事件处理异常) by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

微信赞赏码

文章不错,我要帮站长分担建站费!
天使投赏人

7 Comments

elinx

五月 16, 2017 在 9:39 上午

use \Symfony\Component\Debug\Exception\FlattenException instead of \Symfony\Component\HttpKernel\Exception\FlattenException

    Chris Yue

    五月 16, 2017 在 12:10 下午

    thanks

     

sfer

三月 13, 2016 在 9:55 下午

在Symfony HttpKernel3.0.3版本中:

HttpKernel\Exception\FlattenException 路径的FlattenException文件已经不存在了,

不知道该函数与这个函数是同一个函数不?

Symfony\Component\Debug\Exception\FlattenException

    Chris Yue

    三月 13, 2016 在 9:58 下午

    我觉得显然不是,下一个FlatterException是在debug Component里的,跟HttpKernel没什么关系

    对于3.0的变化,我觉得这个你直接抛出\Exception

     

    sfer

    三月 14, 2016 在 9:49 下午

    Debug Component 里面的FlatterException,是继承的这个接口Symfony\Component\HttpKernel\Exception\HttpExceptionInterface

     

sfer

三月 13, 2016 在 9:19 下午

 

Symfony2.8版本(或者更早版本)之后,RouterListener函数有2个必填参数,所以下面这句还缺少一个参数,请问如何实现ReqestStack及配合使用呢?

$dispatcher->addSubscriber(new HttpKernel\EventListener\RouterListener($matcher));

 

    sfer

    三月 13, 2016 在 9:53 下午

    已经直接new了一个RequestStack

     

发表评论

four × = 24