HttpKernel组件
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 5.2,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
HttpKernel组件
HttpKernel组件提供了一个结构化的过程
请求
成一个响应
通过使用EventDispatcher组件。它足够灵活,可以创建全栈框架(Symfony)、微框架(Silex)或高级CMS系统(Drupal)。ob娱乐下载
安装
1
$编译器需要symfony/httpob娱乐下载-kernel
请注意
如果在Symfony应用程序外部安装此组件,则必须要求ob娱乐下载供应商/ autoload.php
文件,以启用Composer提供的类自动加载机制。读这篇文章欲知详情。
请求的工作流
另请参阅
本文解释了如何在任何PHP应用程序中使用HttpKernel特性作为独立组件。在Syob娱乐下载mfony应用程序中,一切都已经配置好,可以使用了。读了控制器而且事件和事件监听器文章,了解如何使用它在Symfony应用程序中创建控制器和定义事件。ob娱乐下载
每个HTTP网络交互都以请求开始,以响应结束。作为开发人员,您的工作是创建PHP代码来读取请求信息(例如URL),并创建并返回响应(例如HTML页面或JSON字符串)。这是Symfony应用程序中请求工作流的简化概述:ob娱乐下载
- 的用户要求一个资源在一个浏览器;
- 的浏览器发送一个请求到服务器;
- ob娱乐下载给出了应用程序一个请求对象;
- 的应用程序生成一个响应对象的数据初始化请求对象;
- 的服务器返回响应到浏览器;
- 的浏览器显示了资源到用户.
通常,某种框架或系统被构建来处理所有重复的任务(例如路由、安全等),以便开发人员可以构建每一个页面应用程序的。完全如何这些系统的构建差别很大。HttpKernel组件提供了一个接口,该接口形式化了从请求开始并创建适当响应的过程。组件应该是任何应用程序或框架的核心,无论系统的体系结构如何变化:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
名称空间ob娱乐下载\组件\HttpKernel;使用ob娱乐下载\组件\HttpFoundation\请求;接口HttpKernelInterface{/ /……/ * * *@returnResponse响应实例*/公共函数处理(请求$请求, int$类型= self::MASTER_REQUEST, bool$抓=真);}
在内部,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 26 27 28 29
使用ob娱乐下载\组件\EventDispatcher\EventDispatcher;使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpFoundation\RequestStack;使用ob娱乐下载\组件\HttpKernel\控制器\ArgumentResolver;使用ob娱乐下载\组件\HttpKernel\控制器\ControllerResolver;使用ob娱乐下载\组件\HttpKernel\HttpKernel;//创建Request对象$请求=请求::createFromGlobals ();$调度程序=新EventDispatcher ();/ /……添加一些事件监听器//创建控制器和参数解析器$controllerResolver=新ControllerResolver ();$argumentResolver=新ArgumentResolver ();//实例化内核$内核=新HttpKernel ($调度程序,$controllerResolver,新RequestStack (),$argumentResolver);//实际执行内核,将请求转换为响应//通过调度事件,调用控制器,并返回响应$响应=$内核->处理($请求);//发送报头并回显内容$响应->send ();//触发内核。终止事件$内核->终止($请求,$响应);
看到“HttpKernel组件“为了更具体的实施。
有关向下面的事件添加侦听器的一般信息,请参见HttpKernel组件.
谨慎
从3.1年起HttpKernel的实例,接受第四个参数ArgumentResolverInterface.在4.0中,这个参数将成为强制性的。
另请参阅
有一个关于使用HttpKernel组件和其他Symfony组件来创建您自己的框架的精彩系列教程。ob娱乐下载看到简介.
1)kernel.request
事件
典型的目的控件中添加更多信息请求
,初始化部分系统,或返回响应
如果可能(例如,一个拒绝访问的安全层)。
在内部分派的第一个事件HttpKernel:处理是kernel.request
,其中可能有各种不同的侦听器。
这个事件的听众可以是各种各样的。某些侦听器(例如安全侦听器)可能有足够的信息来创建响应
立即对象。例如,如果安全侦听器确定某个用户没有访问权限,则该侦听器可能返回RedirectResponse到登录页面或403拒绝访问响应。
如果一个响应
在此阶段返回,则流程直接跳转到kernel.response事件。
其他侦听器初始化事物或向请求添加更多信息。对象上确定和设置区域设置请求
对象。
另一个常见的侦听器是路由。路由侦听器可以处理请求
并确定应该呈现的控制器(请参阅下一节)。事实上,请求
对象具有一个"属性包,这是一个完美的地方来存储这些额外的,特定于应用程序的数据请求。这意味着如果您的路由器侦听器以某种方式确定了控制器,它可以将其存储在请求
属性(可由控制器解析器使用)。
总的来说,目的kernel.request
事件是创建并返回一个响应
直接,或添加信息请求
(例如设置语言环境或设置一些其他信息请求
属性)。
请注意
属性的响应时kernel.request
事件时,传播停止。这意味着优先级较低的侦听器将不会被执行。
2)解析控制器
假设没有kernel.request
侦听器能够创建响应
在HttpKernel中,下一步是确定和准备(即解析)控制器。控件是最终应用程序代码的一部分,它负责创建和返回响应
对于特定的页面。唯一的要求是它是一个PHP可调用的-即一个函数,一个对象上的方法或关闭
.
但如何请求的确切控制器完全取决于您的应用程序。这是“控制器解析器”的工作——一个实现的类ControllerResolverInterface的构造函数参数之一HttpKernel
.
你的工作是创建一个实现接口的类,并填写它的方法:getController ()
.事实上,一个默认的实现已经存在,你可以直接使用或从中学习:ControllerResolver.这个实现在下面的侧栏中有更多的解释:
1 2 3 4 5 6 7 8
名称空间ob娱乐下载\组件\HttpKernel\控制器;使用ob娱乐下载\组件\HttpFoundation\请求;接口ControllerResolverInterface{公共函数getController(请求$请求);}
在内部,HttpKernel:处理()
方法首先调用getController ()在控制器解析器上。此方法被传递请求
并负责根据请求的信息确定并返回一个PHP可调用对象(控制器)。
3)kernel.controller
事件
典型的目的:在控制器执行之前初始化东西或更改控制器。
在确定控制器可调用对象之后,HttpKernel:处理()
分派kernel.controller
事件。此事件的监听器可能初始化系统的某些部分,这些部分需要在确定某些东西(例如控制器、路由信息)后,但在控制器执行之前初始化。有关一些示例,请参阅下面的Symfony部分。ob娱乐下载
此事件的监听器也可以通过调用完全改变可调用的控制器ControllerEvent: setController在此事件上传递给侦听器的事件对象上。
4)获取控制器参数
接下来,HttpKernel:处理()
调用ArgumentResolverInterface: getArguments ().记住,控制器返回getController ()
是可调用的。的目的getArguments ()
是返回应传递给该控制器的参数数组。具体如何做到这一点完全取决于您的设计,尽管内置ArgumentResolver就是一个很好的例子。
在这一点上,内核有一个PHP可调用对象(控制器)和一个参数数组,当执行该可调用对象时应该传递这些参数。
5)调用控制器
下一步HttpKernel:处理()
Does正在执行控制器。
控制器的工作是为给定的资源构建响应。这可以是一个HTML页面,一个JSON字符串或其他任何东西。与迄今为止流程的其他部分不同,这一步是由“终端开发人员”为构建的每个页面实现的。
通常,控制器将返回一个响应
对象。如果这是真的,那么内核的工作就差不多完成了!在本例中,下一步是kernel.response事件。
但如果控制器返回的不是a响应
,那么内核有更多的工作要做-kernel.view(因为最终目标是总是生成响应
对象)。
请注意
控制器必须返回某物.如果控制器返回零
,则会立即抛出异常。
6)kernel.view
事件
典型的目的:转换非响应
从控制器返回值到响应
如果控制器不返回响应
对象,然后内核分派另一个事件-kernel.view
.此事件的监听器的工作是使用控制器的返回值(例如数据数组或对象)来创建一个对象响应
.
如果你想使用一个“视图”层:而不是返回一个响应
从控制器返回表示页面的数据。此事件的侦听器然后可以使用此数据创建响应
这是在正确的格式(如HTML, JSON等)。
在此阶段,如果没有侦听器对事件设置响应,则抛出异常:要么是控制器或一个视图监听器必须总是返回响应
.
请注意
属性的响应时kernel.view
事件时,传播停止。这意味着优先级较低的侦听器将不会被执行。
7)kernel.response
事件
典型的目的:修改响应
对象
内核的最终目标是转换请求
成一个响应
.的响应
时创建的kernel.request事件返回控制器,或由某个侦听器返回到kernel.view事件。
不管谁创建的响应
,另一事件-kernel.response
之后会被直接发送。此事件的典型侦听器将修改响应
对象的内容,例如修改标头、添加cookie,甚至更改响应
本身(例如,在结束之前注入一些JavaScript< /身体>
HTML响应的标签)。
在此事件被分派之后,最终的响应
对象返回的处理().在最典型的用例中,然后可以调用send ()方法,该方法发送标头并打印响应
内容。
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.exception
事件
典型的目的:处理某种类型的异常并创建适当的响应
返回异常
如果在内部的任何位置抛出异常HttpKernel:处理()
,另一事件-kernel.exception
抛出。在内部,身体处理()
方法封装在try-catch块中。抛出任何异常时,kernel.exception
事件被分派,以便您的系统可以以某种方式响应异常。
向此事件的每个侦听器传递一个ExceptionEvent对象,您可以使用该对象通过getThrowable ()方法。此事件的典型侦听器将检查某种类型的异常并创建适当的错误响应
.
例如,要生成404页面,您可以抛出一个特殊类型的异常,然后在此事件上添加一个侦听器,该侦听器查找该异常并创建并返回404响应
.事实上,HttpKernel组件附带了一个ErrorListener,如果您选择使用它,它将默认执行此操作和更多操作(有关详细信息,请参阅下面的侧栏)。
请注意
属性的响应时kernel.exception
事件时,传播停止。这意味着优先级较低的侦听器将不会被执行。
创建事件监听器
如您所见,您可以创建事件侦听器并将其附加到过程中分派的任何事件HttpKernel:处理()
周期。通常监听器是一个带有被执行方法的PHP类,但它可以是任何东西。有关创建和附加事件侦听器的详细信息,请参见EventDispatcher组件.
对象上的一个常量定义了每个“内核”事件的名称KernelEvents类。此外,每个事件侦听器都传递一个参数,该参数是类的某个子类KernelEvent.该对象包含关于系统当前状态的信息,每个事件都有自己的事件对象:
的名字 | KernelEvents 常数 |
参数传递给侦听器 |
---|---|---|
kernel.request | KernelEvents:请求 |
RequestEvent |
kernel.controller | KernelEvents:控制器 |
ControllerEvent |
kernel.controller_arguments | KernelEvents: CONTROLLER_ARGUMENTS |
ControllerArgumentsEvent |
kernel.view | KernelEvents:视图 |
ViewEvent |
kernel.response | KernelEvents:响应 |
ResponseEvent |
kernel.finish_request | KernelEvents: FINISH_REQUEST |
FinishRequestEvent |
kernel.terminate | KernelEvents:终止 |
TerminateEvent |
kernel.exception | KernelEvents:异常 |
ExceptionEvent |
一个完整的工作示例
当使用HttpKernel组件时,您可以自由地将任何侦听器附加到核心事件,使用实现HttpKernel的任何控制器解析器ControllerResolverInterface并使用任何参数解析器实现ArgumentResolverInterface.然而,HttpKernel组件自带一些内置监听器和其他可以用来创建一个工作示例的东西:
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 37 38
使用ob娱乐下载\组件\EventDispatcher\EventDispatcher;使用ob娱乐下载\组件\HttpFoundation\请求;使用ob娱乐下载\组件\HttpFoundation\RequestStack;使用ob娱乐下载\组件\HttpFoundation\响应;使用ob娱乐下载\组件\HttpKernel\控制器\ArgumentResolver;使用ob娱乐下载\组件\HttpKernel\控制器\ControllerResolver;使用ob娱乐下载\组件\HttpKernel\EventListener\RouterListener;使用ob娱乐下载\组件\HttpKernel\HttpKernel;使用ob娱乐下载\组件\路由\匹配器\UrlMatcher;使用ob娱乐下载\组件\路由\RequestContext;使用ob娱乐下载\组件\路由\路线;使用ob娱乐下载\组件\路由\RouteCollection;$路线=新RouteCollection ();$路线->add (“你好”,新路线(“/ hello /{名称}”, (“_controller”= >函数(请求$请求){返回新响应(sprintf (“你好,% s”,$请求->get (“名字”)));}));$请求=请求::createFromGlobals ();$匹配器=新UrlMatcher ($路线,新RequestContext ());$调度程序=新EventDispatcher ();$调度程序->addSubscriber (新RouterListener ($匹配器,新RequestStack ()));$controllerResolver=新ControllerResolver ();$argumentResolver=新ArgumentResolver ();$内核=新HttpKernel ($调度程序,$controllerResolver,新RequestStack (),$argumentResolver);$响应=$内核->处理($请求);$响应->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\事件\RequestEvent;/ /……公共函数onKernelRequestRequestEvent ($事件){如果(!$事件->isMasterRequest ()) {返回;}/ /……}
定位资源
HttpKernel组件负责Symfony应用程序中使用的包机制。ob娱乐下载包的关键特性是它们允许覆盖应用程序使用的任何资源(配置文件、模板、控制器、翻译文件等)。
这种覆盖机制之所以有效,是因为资源不是通过它们的物理路径而是通过它们的逻辑路径引用的。例如,services . xml
文件存储在资源/ config /
一个名为FooBundle的包的目录被引用为@FooBundle /资源/配置/ services . xml
.当应用程序覆盖该文件时,即使您更改了FooBundle的目录,该逻辑路径也将工作。
HttpKernel组件提供了一个方法locateResource ()可用于将逻辑路径转换为物理路径:
1
$路径=$内核->locateResource (“@FooBundle /资源/配置/ services . xml”);