HttpKernel组件
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 3.0,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
HttpKernel组件
HttpKernel组件提供了一个结构化的过程
请求
成一个响应
通过使用EventDispatcher组件。它足够灵活,可以创建全栈框架(Symfony)、微框架(Silex)或高级CMS系统(Drupal)。ob娱乐下载
安装
你可以用两种不同的方式安装组件:
- 通过Composer安装(
ob娱乐下载symfony / http-kernel
在Packagist); - 使用官方Git存储库(https://github.com/ob娱乐下载symfony/http-kernel).
然后,要求供应商/ autoload.php
文件以启用Composer提供的自动加载机制。否则,您的应用程序将无法找到这个Symfony组件的类。ob娱乐下载
请求的工作流
每个HTTP网络交互都以请求开始,以响应结束。作为开发人员,您的工作是创建PHP代码来读取请求信息(例如URL),并创建并返回响应(例如HTML页面或JSON字符串)。
通常,构建某种框架或系统来处理所有重复的任务(例如路由、安全等),以便开发人员可以轻松地构建每个任务页面应用程序的。完全如何这些系统的构建差别很大。HttpKernel组件提供了一个接口,该接口形式化了从请求开始并创建适当响应的过程。组件应该是任何应用程序或框架的核心,无论系统的体系结构如何变化:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
名称空间ob娱乐下载\组件\HttpKernel;使用ob娱乐下载\组件\HttpFoundation\请求;接口HttpKernelInterface{/ /……/ * * *@returnResponse响应实例*/公共函数处理(请求$请求,$类型= self:: MASTER_REQUEST,$抓=真);}
在内部,HttpKernel:处理()的具体实施HttpKernelInterface:处理()-定义一个以请求以a结尾响应.
这个工作流的确切细节是理解内核(以及Symfony Framework或任何其他使用内核的库)如何工作的关键。ob娱乐下载
HttpKernel:由事件驱动
的HttpKernel:处理()
方法通过调度事件在内部工作。这使得方法既灵活,又有点抽象,因为用HttpKernel构建的框架/应用程序的所有“工作”实际上都是在事件侦听器中完成的。
为了帮助解释这个过程,本文档考察了这个过程的每个步骤,并讨论了HttpKernel的一个具体实现——Symfony框架——是如何工作的。ob娱乐下载
最初,使用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
使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpKernel\HttpKernel;使用ob娱乐下载\组件\EventDispatcher\EventDispatcher;使用ob娱乐下载\组件\HttpKernel\控制器\ControllerResolver;//创建Request对象$请求=请求::createFromGlobals ();$调度程序=新EventDispatcher ();/ /……添加一些事件监听器//创建控制器解析器$解析器=新ControllerResolver ();//实例化内核$内核=新HttpKernel ($调度程序,$解析器);//实际执行内核,将请求转换为响应//通过调度事件,调用控制器,并返回响应$响应=$内核->处理($请求);//发送报头并回显内容$响应->send ();//触发内核。终止事件$内核->终止($请求,$响应);
看到“HttpKernel组件“为了更具体的实施。
有关向下面的事件添加侦听器的一般信息,请参见HttpKernel组件.
另请参阅
有一个关于使用HttpKernel组件和其他Symfony组件来创建您自己的框架的精彩系列教程。ob娱乐下载看到简介.
1)kernel.request
事件
典型的目的控件中添加更多信息请求
,初始化部分系统,或返回响应
如果可能(例如,一个拒绝访问的安全层)。
在内部分派的第一个事件HttpKernel:处理是kernel.request
,其中可能有各种不同的侦听器。
这个事件的听众可以是各种各样的。某些侦听器(例如安全侦听器)可能有足够的信息来创建响应
立即对象。例如,如果安全侦听器确定某个用户没有访问权限,则该侦听器可能返回RedirectResponse到登录页面或403拒绝访问响应。
如果一个响应
在此阶段返回,则流程直接跳转到kernel.response事件。
其他侦听器只是初始化事物或向请求添加更多信息。对象上确定和设置区域设置请求
对象。
另一个常见的侦听器是路由。路由侦听器可以处理请求
并确定应该呈现的控制器(请参阅下一节)。事实上,请求
对象具有一个"属性包,这是一个完美的地方来存储这些额外的,特定于应用程序的数据请求。这意味着如果您的路由器侦听器以某种方式确定了控制器,它可以将其存储在请求
属性(可由控制器解析器使用)。
总的来说,目的kernel.request
事件是创建并返回一个响应
直接,或添加信息请求
(例如设置语言环境或设置一些其他信息请求
属性)。
请注意
属性的响应时kernel.request
事件时,传播停止。这意味着优先级较低的侦听器将不会被执行。
kernel.request
在Symfonob娱乐下载y框架中
最重要的听众kernel.request
的ob娱乐下载RouterListener.该类执行路由层,该层返回一个数组匹配请求的信息,包括_controller
以及路由模式中的任何占位符(例如。{蛞蝓}
).看到路由组件.
该信息数组存储在请求对象的属性
数组中。在这里添加路由信息还不做任何事情,但将在解析控制器时使用。
2)解析控制器
假设没有kernel.request
侦听器能够创建响应
在HttpKernel中,下一步是确定和准备(即解析)控制器。控件是最终应用程序代码的一部分,它负责创建和返回响应
对于特定的页面。唯一的要求是它是一个PHP可调用的-即一个函数,一个对象上的方法,或一个关闭
.
但如何请求的确切控制器完全取决于您的应用程序。这是“控制器解析器”的工作——一个实现的类ControllerResolverInterface的构造函数参数之一HttpKernel
.
你的工作是创建一个实现接口的类,并填写它的两个方法:getController
而且getArguments
.事实上,一个默认的实现已经存在,你可以直接使用或从中学习:ControllerResolver.这个实现在下面的侧栏中有更多的解释:
1 2 3 4 5 6 7 8 9 10
名称空间ob娱乐下载\组件\HttpKernel\控制器;使用ob娱乐下载\组件\HttpFoundation\请求;接口ControllerResolverInterface{公共函数getController(请求$请求);公共函数getArguments(请求$请求,$控制器);}
在内部,HttpKernel:处理
方法首先调用getController ()在控制器解析器上。此方法被传递请求
并负责根据请求的信息确定并返回一个PHP可调用对象(控制器)。
第二种方法,getArguments (),将被称为另一个事件后-kernel.controller
-被分派。
在Symfony框架中解析控制器ob娱乐下载
Symfob娱乐下载ony框架使用内置的ControllerResolver类(实际上,它使用了一个带有下面提到的一些额外功能的子类)。类上的信息请求
对象的属性
财产在RouterListener
.
getController
的ControllerResolver
寻找一个_controller
按下请求
对象的attributes属性(请记住,此信息通常放在请求
通过RouterListener
).然后这个字符串被转换成一个PHP可调用对象,方法如下:
-
一个)
AcmeDemoBundle:默认值:索引
的格式_controller
关键 -
被更改为另一个字符串,该字符串包含控制器的完整类名和方法名,遵循Symfony中使用的约定。ob娱乐下载
Acme \ DemoBundle \控制器\ DefaultController: indexAction
.这个变换是特定于ControllerResolverSymfony框架使用的子类。ob娱乐下载 - b)你的控制器类的一个新实例用no
- 构造函数参数。
- c)控制器实现ContainerAwareInterface,
-
setContainer
在控制器对象上调用,并将容器传递给它。此步骤也是特定于ControllerResolverSymfony框架使用的子类。ob娱乐下载
3)kernel.controller
事件
典型的目的:在控制器执行之前初始化东西或更改控制器。
在确定控制器可调用对象之后,HttpKernel:处理
分派kernel.controller
事件。此事件的监听器可能初始化系统的某些部分,这些部分需要在确定某些东西(例如控制器、路由信息)后,但在控制器执行之前初始化。有关一些示例,请参阅下面的Symfony部分。ob娱乐下载
此事件的监听器也可以通过调用完全改变可调用的控制器FilterControllerEvent: setController在此事件上传递给侦听器的事件对象上。
kernel.controller
在Symfonob娱乐下载y框架中
有一些小的听众kernel.controller
事件,并且许多处理在启用剖ob娱乐下载析器时收集剖析器数据。
一位有趣的听众来自SensioFrameworkExtraBundle,它与Symfony标准版一起打包。ob娱乐下载这个监听器@ParamConverter函数允许你传递一个完整的对象(例如a帖子
对象)赋给控制器,而不是标量值(例如id
参数)。〇倾听者ParamConverterListener
-使用反射来查看控制器的每个参数,并尝试使用不同的方法将它们转换为对象,然后存储在属性
的属性请求
对象。阅读下一节,了解为什么这很重要。
4)获取控制器参数
接下来,HttpKernel:处理
调用getArguments ().记住,控制器返回getController
是可调用的。的目的getArguments
是返回应传递给该控制器的参数数组。具体如何做到这一点完全取决于您的设计,尽管内置ControllerResolver就是一个很好的例子。
在这一点上,内核有一个PHP可调用对象(控制器)和一个参数数组,当执行该可调用对象时应该传递这些参数。
5)调用控制器
下一步很简单!HttpKernel:处理
执行控制器。
控制器的工作是为给定的资源构建响应。这可以是一个HTML页面,一个JSON字符串或其他任何东西。与迄今为止流程的其他部分不同,这一步是由“终端开发人员”为构建的每个页面实现的。
通常,控制器将返回一个响应
对象。如果这是真的,那么内核的工作就差不多完成了!在本例中,下一步是kernel.response事件。
但如果控制器返回的不是a响应
,那么内核有更多的工作要做-kernel.view(因为最终目标是总是生成响应
对象)。
请注意
控制器必须返回某物.如果控制器返回零
,则会立即抛出异常。
6)kernel.view
事件
典型的目的:转换非响应
从控制器返回值到响应
如果控制器不返回响应
对象,然后内核分派另一个事件-kernel.view
.此事件的监听器的工作是使用控制器的返回值(例如数据数组或对象)来创建一个对象响应
.
如果你想使用一个“视图”层:而不是返回一个响应
从控制器返回表示页面的数据。此事件的侦听器然后可以使用此数据创建响应
这是在正确的格式(如HTML, JSON等)。
在此阶段,如果没有侦听器对事件设置响应,则抛出异常:要么是控制器或一个视图监听器必须总是返回响应
.
请注意
属性的响应时kernel.view
事件时,传播停止。这意味着优先级较低的侦听器将不会被执行。
kernel.view
在Symfonob娱乐下载y框架中
类的默认侦听器在Symfony框架中没有ob娱乐下载kernel.view
事件。然而,有一个核心bundle -SensioFrameworkExtraBundle-做向此事件添加侦听器。如果你的控制器返回一个数组,你把@Template注释,然后这个侦听器呈现一个模板,将您从控制器返回的数组传递给该模板,并创建一个响应
包含从该模板返回的内容。
此外,一个流行的社区捆绑包欧宝体育平台怎么样FOSRestBundle在这个事件上实现一个监听器,目的是给你一个健壮的视图层,能够使用单个控制器返回许多不同的内容类型的响应(例如HTML、JSON、XML等)。
7)kernel.response
事件
典型的目的:修改响应
对象
内核的最终目标是转换请求
成一个响应
.的响应
时创建的kernel.request事件返回控制器,或由某个侦听器返回到kernel.view事件。
不管谁创建的响应
,另一事件-kernel.response
之后会被直接发送。此事件的典型侦听器将修改响应
对象的内容,例如修改标头、添加cookie,甚至更改响应
本身(例如,在结束之前注入一些JavaScript< /身体>
HTML响应的标签)。
在此事件被分派之后,最终的响应
对象返回的处理().在最典型的用例中,然后可以调用send ()方法,该方法发送标头并打印响应
内容。
kernel.response
在Symfonob娱乐下载y框架中
在Symfony框架中,这个事件有几个较小的侦听器,大多数侦听器以某种方式修改响应。ob娱乐下载例如,WebDebugToolbarListener的页面底部注入一些JavaScriptdev
使web调试工具栏显示的环境。另一个侦听器,ContextListener将当前用户的信息序列化到会话中,以便在下一个请求时可以重新加载它。
8)kernel.terminate
事件
典型的目的:在响应流发送给用户后执行一些“重”操作
HttpKernel进程的最后一个事件是kernel.terminate
并且是唯一的,因为它发生了后的HttpKernel:处理
方法,并且在将响应发送给用户之后。回想一下上面,然后使用内核的代码,像这样结束:
1 2 3 4 5
//发送报头并回显内容$响应->send ();//触发内核。终止事件$内核->终止($请求,$响应);
如你所见,通过打电话内核- >终止
发送响应后,您将触发kernel.terminate
事件,在此事件中,您可以执行某些可能延迟的操作,以便尽快向客户端返回响应(例如发送电子邮件)。
谨慎
在内部,HttpKernel使用fastcgi_finish_requestPHP函数。这意味着,目前,只有PHP FPM服务器API能够在服务器的PHP进程仍然执行某些任务时向客户端发送响应。对于所有其他服务器api,监听器kernel.terminate
仍然执行,但是直到它们全部完成才将响应发送到客户端。
请注意
使用kernel.terminate
事件是可选的,并且只应该在内核实现时调用TerminableInterface.
kernel.terminate
在Symfonob娱乐下载y框架中
如果你使用SwiftmailerBundle与Symfony一起使用ob娱乐下载内存
假脱机,然后EmailSenderListener激活,它实际上会发送您在请求期间计划发送的任何电子邮件。
异常处理:kernel.exception
事件
典型的目的:处理某种类型的异常并创建适当的响应
返回异常
如果在内部的任何位置抛出异常HttpKernel:处理
,另一事件-kernel.exception
抛出。在内部,身体处理
函数封装在try-catch块中。抛出任何异常时,kernel.exception
事件被分派,以便您的系统可以以某种方式响应异常。
向此事件的每个侦听器传递一个GetResponseForExceptionEvent对象,您可以使用该对象通过getException ()方法。此事件的典型侦听器将检查某种类型的异常并创建适当的错误响应
.
例如,要生成404页面,您可以抛出一个特殊类型的异常,然后在此事件上添加一个侦听器,该侦听器查找该异常并创建并返回404响应
.事实上,HttpKernel组件附带了一个ExceptionListener,如果您选择使用它,它将默认执行此操作和更多操作(有关详细信息,请参阅下面的侧栏)。
请注意
属性的响应时kernel.exception
事件时,传播停止。这意味着优先级较低的侦听器将不会被执行。
kernel.exception
在Symfonob娱乐下载y框架中
有两个主要的监听器kernel.exception
当使用Symfony框架时。ob娱乐下载
HttpKernel中的ExceptionListener
第一个是HttpKernel组件的核心,并被调用ExceptionListener.听众有几个目标:
- 抛出的异常被转换为FlattenException对象,其中包含关于请求的所有信息,但可以打印和序列化。
- 如果原始异常实现HttpExceptionInterface,然后
getStatusCode
而且getHeaders
异常时调用,并用于填充FlattenException
对象。这个想法是在创建最终响应时的下一步中使用这些。 - 执行控制器并传递扁平异常。要呈现的确切控制器作为构造函数参数传递给此侦听器。该控制器将返回final
响应
对于此错误页。
安全中的ExceptionListener
另一个重要的监听器是ExceptionListener.此侦听器的目标是处理安全异常,并且在适当时,帮助要进行身份验证的用户(例如重定向到登录页面)。
创建事件监听器
如您所见,您可以创建事件侦听器并将其附加到过程中分派的任何事件HttpKernel:处理
周期。通常监听器是一个带有被执行方法的PHP类,但它可以是任何东西。有关创建和附加事件侦听器的详细信息,请参见EventDispatcher组件.
对象上的一个常量定义了每个“内核”事件的名称KernelEvents类。此外,每个事件侦听器都传递一个参数,该参数是类的某个子类KernelEvent.该对象包含关于系统当前状态的信息,每个事件都有自己的事件对象:
的名字 | KernelEvents 常数 |
参数传递给侦听器 |
---|---|---|
kernel.request | KernelEvents:请求 |
GetResponseEvent |
kernel.controller | KernelEvents:控制器 |
FilterControllerEvent |
kernel.view | KernelEvents:视图 |
GetResponseForControllerResultEvent |
kernel.response | KernelEvents:响应 |
FilterResponseEvent |
kernel.finish_request | KernelEvents: FINISH_REQUEST |
FinishRequestEvent |
kernel.terminate | KernelEvents:终止 |
PostResponseEvent |
kernel.exception | KernelEvents:异常 |
GetResponseForExceptionEvent |
一个完整的工作示例
使用HttpKernel组件时,您可以自由地将任何侦听器附加到核心事件,并使用实现HttpKernel的任何控制器解析器ControllerResolverInterface.然而,HttpKernel组件自带一些内置的监听器和一个内置的ControllerResolver,可以用来创建一个工作示例:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpFoundation\RequestStack;使用ob娱乐下载\组件\HttpFoundation\响应;使用ob娱乐下载\组件\HttpKernel\HttpKernel;使用ob娱乐下载\组件\EventDispatcher\EventDispatcher;使用ob娱乐下载\组件\HttpKernel\控制器\ControllerResolver;使用ob娱乐下载\组件\HttpKernel\EventListener\RouterListener;使用ob娱乐下载\组件\路由\RouteCollection;使用ob娱乐下载\组件\路由\路线;使用ob娱乐下载\组件\路由\匹配器\UrlMatcher;使用ob娱乐下载\组件\路由\RequestContext;$路线=新RouteCollection ();$路线->add (“你好”,新路线(“/ hello /{名称}”,数组(“_controller”= >函数(请求$请求){返回新响应(sprintf (“你好,% s”,$请求->get (“名字”)));}));$请求=请求::createFromGlobals ();$匹配器=新UrlMatcher ($路线,新RequestContext ());$调度程序=新EventDispatcher ();$调度程序->addSubscriber (新RouterListener ($匹配器,新RequestStack ()));$解析器=新ControllerResolver ();$内核=新HttpKernel ($调度程序,$解析器);$响应=$内核->处理($请求);$响应->send ();$内核->终止($请求,$响应);
子请求
除了被发送到的main请求之外HttpKernel:处理
,你也可以发送所谓的“分请求”。子请求的外观和行为与其他请求相似,但通常只用于呈现页面的一小部分,而不是整个页面。最常见的是从控制器发出子请求(或者从模板内部发出,由控制器渲染)。
要执行子请求,使用HttpKernel:处理
,但将第二个参数更改如下:
12 3 4 5 6 7 8 9 10 11 12
使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpKernel\HttpKernelInterface;/ /……//根据需要手动创建一些其他请求$请求=新请求();//例如,可能手动设置它的_controller$请求->属性->集(“_controller”,“……”);$响应=$内核->处理($请求, HttpKernelInterface::SUB_REQUEST);//对这个响应执行一些操作
这创建了另一个完整的请求-响应周期,其中新的请求
被转化为响应
.内部唯一的区别是一些侦听器(例如安全)可能只对主请求起作用。的某个子类传递给每个侦听器KernelEvent,他的isMasterRequest ()可用于检查当前请求是“主”请求还是“子”请求。
例如,只需要对主请求起作用的侦听器可能是这样的:
1 2 3 4 5 6 7 8 9 10 11
使用ob娱乐下载\组件\HttpKernel\事件\GetResponseEvent;/ /……公共函数onKernelRequest(GetResponseEvent$事件){如果(!$事件->isMasterRequest ()) {返回;}/ /……}