HttpKernel组件:HttpKernel类
编辑本页HttpKernel组件:HttpKernel类
如果您现在要使用我们的框架,您可能必须添加对自定义错误消息的支持。我们确实有404和500错误支持,但响应是硬编码在框架本身。不过,使它们可定制很简单:分派一个新事件并监听它。正确地执行它意味着侦听器必须调用常规控制器。但是如果错误控制器抛出异常怎么办?你会陷入一个无限循环。应该有更简单的方法,对吧?
进入HttpKernel
类。而不是一遍又一遍地解决同样的问题,而不是每次都重新发明轮子HttpKernel
类的通用、可扩展和灵活实现HttpKernelInterface
.
这个类与我们迄今为止编写的框架类非常相似:它在处理请求期间在某些战略点分派事件,它使用控制器解析器来选择要将请求分派到的控制器,作为额外的奖励,它会处理边缘情况,并在出现问题时提供良好的反馈。
下面是新的框架代码:
1 2 3 4 5 6 7 8
/ / example.com/src/Simplex/Framework.php名称空间单纯形;使用ob娱乐下载\组件\HttpKernel\HttpKernel;类框架扩展HttpKernel{}
新的前端控制器:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/ / example.com/web/front.phprequire_once__DIR__.“/ . . /供应商/ autoload.php”;使用ob娱乐下载\组件\EventDispatcher\EventDispatcher;使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpFoundation\RequestStack;使用ob娱乐下载\组件\HttpFoundation\响应;使用ob娱乐下载\组件\HttpKernel;使用ob娱乐下载\组件\路由;$请求=请求::createFromGlobals ();$requestStack=新RequestStack ();$路线=包括__DIR__.“/ . . / src / app.php”;$上下文=新路由\ RequestContext ();$匹配器=新路由\匹配器\ UrlMatcher ($路线,$上下文);$controllerResolver=新HttpKernel \控制器\ ControllerResolver ();$argumentResolver=新HttpKernel \控制器\ ArgumentResolver ();$调度程序=新EventDispatcher ();$调度程序->addSubscriber (新HttpKernel \ EventListener \ RouterListener ($匹配器,$requestStack));$框架=新单纯形\框架($调度程序,$controllerResolver,$requestStack,$argumentResolver);$响应=$框架->处理($请求);$响应->send ();
RouterListener
是我们在框架中使用的相同逻辑的实现:它匹配传入请求并使用路由参数填充请求属性。
现在,我们的代码比以往任何时候都更简洁、更健壮、更强大。例如,使用内置的ErrorListener
要使错误管理可配置:
1 2 3 4 5 6
$errorHandler=函数组ob娱乐下载件(Symfony \ \ ErrorHandler \ \ FlattenException异常$异常){$味精=“出事了!”('.$异常->getMessage()。“)”;返回新响应($味精,$异常->getStatusCode ());};$调度程序->addSubscriber (新HttpKernel \ EventListener \ ErrorListener ($errorHandler));
ErrorListener
给你一个FlattenException
实例,而不是抛出异常
或错误
实例来简化异常操作和显示。它可以接受任何有效的控制器作为异常处理程序,所以你可以创建一个ErrorController类,而不是使用闭包:
1 2 3 4
$侦听器=新HttpKernel \ EventListener \ ErrorListener (“日历\控制器\ ErrorController:异常”);$调度程序->addSubscriber ($侦听器);
错误控制器如下所示:
12 3 4 5 6 7 8 9 10 11 12 13 14 15
/ / example.com/src/Calendar/Controller/ErrorController.php名称空间日历\控制器;使用ob娱乐下载\组件\ErrorHandler\异常\FlattenException;使用ob娱乐下载\组件\HttpFoundation\响应;类ErrorController{公共函数异常(FlattenException$异常){$味精=“出事了!”('.$异常->getMessage()。“)”;返回新响应($味精,$异常->getStatusCode ());}}
瞧!简单且可定制的错误管理。如果你ErrorController
抛出一个异常,HttpKernel会很好地处理它。
在第二章中,我们讨论了回应::准备()
方法,该方法确保响应与HTTP规范兼容。在将Response发送给客户端之前调用它可能是个好主意;这就是ResponseListener
:
1
$调度程序->addSubscriber (新HttpKernel \ EventListener \ ResponseListener (“utf - 8”));
如果您希望对流响应提供开箱即用的支持,请订阅StreamedResponseListener
:
1
$调度程序->addSubscriber (新HttpKernel \ EventListener \ StreamedResponseListener ());
在控制器中,返回aStreamedResponse
实例,而不是响应
实例。
提示
读了内置Symfonyob娱乐下载事件参考了解更多关于HttpKernel分派的事件以及它们如何允许你改变请求流的信息。
现在,让我们创建一个监听器,它允许控制器返回一个字符串,而不是一个完整的Response对象:
12 3 4 5 6 7 8 9 10 11 12
类LeapYearController{公共函数指数($一年){$leapYear=新LeapYear ();如果($leapYear->isLeapYear ($一年)) {返回“是的,今年是闰年!”;}返回“不,今年不是闰年。”;}}
为了实现这个特性,我们将侦听kernel.view
事件,该事件在控制器被调用后被触发。它的目标是将控制器返回值转换为适当的Response实例,但仅在需要时:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/ / example.com/src/Simplex/StringResponseListener.php名称空间单纯形;使用ob娱乐下载\组件\EventDispatcher\EventSubscriberInterface;使用ob娱乐下载\组件\HttpFoundation\响应;使用ob娱乐下载\组件\HttpKernel\事件\ViewEvent;类StringResponseListener实现了EventSubscriberInterface{公共函数onView(ViewEvent$事件){$响应=$事件->getControllerResult ();如果(is_string ($响应)) {$事件->setResponse (新响应($响应));}}公共静态函数getSubscribedEvents(){返回[“kernel.view”= >“onView”];}}
代码很简单,因为kernel.view
事件只有在控制器返回值不是Response时才会触发,因为在事件上设置响应会停止事件传播(我们的侦听器不能干扰其他视图侦听器)。
不要忘记在前端控制器中注册它:
1
$调度程序->addSubscriber (新单纯形\ StringResponseListener ());
请注意
如果你忘记注册订阅者,HttpKernel会抛出一个异常,并附上一条漂亮的消息:控制器必须返回一个响应(不,这不是闰年。鉴于)。
.
在这一点上,我们的整个框架代码是尽可能紧凑的,它主要由现有库的程序集组成。扩展是一个注册事件监听器/订阅者的问题。
希望您现在已经更好地理解了为什么使用简单的外观HttpKernelInterface
是如此强大。它的默认实现,HttpKernel
,为您提供了许多很酷的功能,随时可以开箱即用,无需任何努力。因为HttpKernel实际上是驱动Symfony框架的代码,所以你拥有了两个世界的优点:一个自定义的框架,根据你的需要ob娱乐下载量身定制,但基于一个被证明适用于许多网站的坚如磐石和良好维护的底层架构;经过安全问题审计的代码,并已被证明具有良好的可伸缩性。