·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> php网站开发 >> Symfony2 HttpKernel事件驱动

Symfony2 HttpKernel事件驱动

作者:佚名      php网站开发编辑:admin      更新时间:2022-07-23
Symfony2 HttpKernel事件驱动HttpKernel:事件驱动 Symfony2框架层和应用层的工作都是在HttpKernel::handle()方法中完成,HttpKernel::handle()的内部的实现其实是通过调度事件(HttpKernel内的事件监听器)来完成的,相当于把所有组件都整合成完整的应用。 使用HttpKernel很简单,只需要创建一个EventDispatcher(事件分发器)和controller resolver(Controller解析器),可以实现更多的事件监听器丰富应用的功能: 1)kernel.requestEvent 实现kernel.request事件目的是为了添加更多信息到Request对象,或者得到返回的Response对象(例如:从缓存中获取又或者security层拒绝访问) kernel.request事件是HttpKernel::handle()调度的第一个事件,那么监听该事件的多个监听器就会被执行。 监听kernel.request事件的监听器多种多样,它们的行为各不相同,例如security监听器判断用户没有足够的权限的时候一个RedirectResponse对象,如果当前直接返回Response对象,那么就会直接执行 kernel.response 事件: 其它的监听器实现一些初始化或者添加更多的信息到Request对象。 例如路由监听器,路由监听器从Request对象中获取路由相关的信息,经过进一步加工,确定处理请求的Controller,并且把相应的信息保存到Request对象里的‘attribute’里,这些信息都会被Controller解析器使用的,所以可以实现监听器之间的解耦。 总得来说,实现kernel.request事件的目的要么就是直接创建和返回Response对象,要么就是添加更多的信息到Request对象。
RouterListener是Symfony框架中实现kernel.request事件的最重要监听器,RouterListener在路由层中执行,返回一个包含符合当前请求的路由信息的数组,例如路由匹配模式里面的_controller和请求的参数({name})。这些信息都会存放在Request里的attributes数组里面,目前只是会添加路由信息到Request对象中还没有做其它的动作,但是解析Controller的时候会被用到。
2) Resolve the Controller 假设实现kernel.request事件的时候没有创建和返回Response对象,那么下一步就是确定、解析controller和controller需要的参数。controller部分是应用层的最后一个堡垒,负责创建和返回包含一个特定页面的Response对象。如何确定被请求的controller完全取决于应用程序,这个工作有controller解析器来完成——一个是实现ControllerResolverInterface的类,同时也是HttpKernel构造函数的一个参数。 实现ControllerResolverInterface的两个方法getController和getArguments: HttpKernel::handle()首先调用controller resolver 的 getController()方法,并向该方法传入Request对象,controller resolver根据Request包含的信息确定并返回controller。 第二个方法,getArguments()会在kernel.controller事件被调度的时候执行。
解析ControllerSymfony框架使用内置的ControllerResolver(实质上是使用了一个有额外的功能的子类),该解析器利用了RouterListener保存到Request对象的attributes属性里信息来确定controller。getControllerControllerResolver在Request对象的attributes数组中查找 _controller 键(这些信息实际上是由RouterListener存放进Request对象中的):a) 如果_controller 键对应AcmeDemoBundle:Default:index 这个格式的值,那么该值就包含了类名和方法名,可以被Symfony框架解析成为,例如:Acme\DemoBundle\Controller\DefaultController::indexAction,这个转换是由Symfony框架的特定的ControllerResolver的子类完成的。b) 你的controller类会被实例化,而且该controller类必须包含一个无参的构造函数。c) 如果你的controller还实现了ContainerAwareInterface,那么setContainer方法就会被调用,container就会被注入到controller中,这个实现也是由Symfony框架的特定的ControllerResolver的子类完成的。上面也有一些其他变化过程,例如你把你的controller配置成为service。
3) Thekernel.controllerEvent

kernel.controller事件是在controller被执行前初始化一些信息或者改变controller对象。

被调用的controller确定之后,HttpKernel::handle()就会调度kernel.controller事件。在系统的某部分被确定后(例如:controller、路由信息等)但是这些部分被执行前,监听kernel.controller事件的监听器就会运行了。

kernel.controllerSymfony框架有几个kernel.controller事件的监听器,多数都是处理分析数据的。SensioFrameworkExtraBundle中一个监听器ParamConverter允许我们把一个对象作为参数传入到controller中,而不是字符串或者数值参数。
4)获得controller的参数 getAttributes()方法是返回一个参数数组,这个参数数组会被传递给controller,我们也可以自定义该方法,也可以使用Symfony框架内置的。
到了这一步,kernel已经获得了controller和controller运行时需要的参数了。
Symfony框架获得controller的参数
ControllerResolver使用放射机制获得被调用的controller的方法的参数列表。遍历该列表,使用下面的步骤来确定参数列表中一一对应的值:
a) 使用参数作为键查找Request对象中的attributes数组,如果找到,那么相应的值会传入到controller的方法中,例如:controller方法的第一个参数是$name,那么在Request的attributes数组中包含$attributes['name']的值,那么$attributes['name']就会被使用。
b) 如果该该参数在Symfony配置routing的时候被指定,那么就会跳过对该参数的查找。

5)调用controller

这一步,controller就会被执行。 controller会创建包含特定页面或者json的Response对象,这也是应用层的最后一个步骤。 如果controller返回的是Response对象,那么下一步kernel.response事件就会触发,否者kernel.view事件就会被触发。
controller必须要有返回值,如果返回null,程序会报错

6) kernel.view事件

c