Symfony2内部是怎样工作的以及我们如何来扩展它呢?
从外部整体上看,symfony2代码是由许多独立的层构成,每一层都是建立在前一层基础之上。其中,自动加载时不受框架直接管理的,它完全是在UniversalClassLoader类和src/autoload.php文件的帮助下独立完成的。

HttpFoundation 组件
最深层次的是HttpFoundation组件,它提供了处理HTTP所需的主要对象。是一个对一些PHP函数和变量的面向对象抽象。
包括:
Request 类,抽象了PHP中主要的全局变量$_GET,$_POST,$_COOKIE,$_FILES 和 $_SERVER。
Response类,抽象类一些PHP函数比如header(), setcookie()和echo();
Session 类和SessionStorageInterface接口则是抽象了Session管理Session_*()函数。

HttpKernel 组件:
在HttpFoundation组件之上创建的一个组件,它处理HTTP的动态部分。它是为了能够通过标准的方式来处理request,而对Request和Response对象的一个最小封装。同时它提供了一些扩展点和工具,让它成为创建一个web框架的最理想的开始点。

另外,Dependency Injection组件和强大的插件系统bundles让它增加了可配置性和扩展性。

FrameworkBundle Bundle
FrameworkBundle bundle 是一个bundle,它是构成轻量级快速MVC框架的主要组件和类库。

Kernel
HttpKernel类是Symfony2的中心类,它负责处理客户端请求。它的主要任务就是把Request对象转换成Response对象。每个Symfony2核心实现HttpKernelInterface接口。

function handle(Request $request,$type=self::MASTER_REQUEST,$catch=true)

Controller
Kernel依靠Controller来吧Request转换为Response。 Controller可以是任何有效的PHP调用。Kernel委托选择哪个Controller应该被执行给一个ControllerResolverInterface接口的实现者。

public function getController(Request $request);
public function getArguments(Request $request,$controller);

其中,getController()方法返回一个和给定的Request相对于的Controller(一个PHP调用)。ControllerResolver的默认实现是查找Request的一个_controller属性,它的值是一个class::method 格式的字符串。比如Bundle\BlogBundle\PostController::indexAction 。默认的实现使用RouterListener来定义Request的属性 _controller。getArguments()方法返回一个输入参数数组来传递给Controller调用。默认实现会根据Request属性自动的获取这些输入参数。

从Request属性中匹配Controller方法的输入参数:Symfony2对于每一个方法的输入参数都会是这从Request中查找其同名属性,如果没有定义,就会取该输入参数的默认值。

// Symfony2 从Request属性中查找 'id' 属性(强制)
// 和一个'admin' 属性 (可选)
public function showAction($id, $admin = true)
{
// ...
}

处理请求:handle()方法需要一个Request参数并且永远都必须返回一个Response。要转换Request,handle()需要依靠一个分析器和一个事件通知顺序链。
1. 在处理任何事情之前,kernel.request事件将被通知 --如果一个监听者返回了一个Response,那么它会直接跳至第8步。
2. 分析器被调用来判断哪个Controller将被执行。
3. kernel.controller事件监听器现在开始处理Controller调用(改变它,封装它...)
4. Kernel检查Controller是否是一个合法可调用的PHP回调。
5. 分析器被调用来决定传递给controller的参数
6. Kernel调用Controller
7. 如果Controller没有返回Response对象,kernel.view事件监听器会把Controller的返回值转换成一个Response。
8. kernel.response事件监听器开始处理Response(内容和头部);
9. Response对象被返回。

如果在这个过程中有一个异常被抛出,kernel.exception就会被通知,监听器就把异常转换为一个Response,之后kernel.response事件就会被通知,如果没能转换,该异常就会被抛出。

如果你不想异常被捕获,你可以通过传递一个false作为第三个参数到handle()方法,来关闭kernel.exception事件。

内部请求
在处理一个主请求的任何时候,子请求都可以被处理。你可以传递一个请求类型到handle()方法,作为它的第二个参数。

HttpKernelInterface::MASTER_ReQUEST;
HttpKernelInterface::SUB_REQUEST

这些类型会根据需要传递给所有的事件和监听器。

事件
Kernel抛出的每一个事件都会是KernelEvent类的子类。这就意味着每个事件都可以访问相同的基础信息。
getRequestType() 返回请求的类型(HttpKernelInterface::MASTER_REQUEST 或者 HttpKernelInterface::SUB_REQUEST;
getKernel() 返回处理请求的Kernel
getRequest() 返回一个当前被处理的请求

getRequestType()方法允许监听器知道请求的类型。比如,如果一个监听器必须是主请求才能激活它,你可以把该代码添加到你监听器方法的开头:

use Symfony\Component\HttpKernel\HttpKernelInterface;
if(HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()){
//立刻返回
return;
}

kernel.request 事件
事件类:GetResponseEvent

该事件的目标是立刻返回一个Response对象或者创建一个在事件结束后Controller可以调用的变量。任何监听器都可以通过event的setResponse()方法返回一个Response对象,当有Response对象被返回时,其它的监听器就不能在被调用了。

FrameworkBundle使用事件通过RouterListener来发布一个_controller 请求属性。
RequestListener 使用一个RouterInterface对象匹配Request,决定哪个Controller的名字会被存储到_controller的请求属性里。

kernel.controller 事件:
事件类: FilterControllerEvent

FrameworkBundle不会使用该事件,但是该事件可以被作为一个修改要执行的controller的一个入口点。

use Symfony\Component\Httpkernel\Event\FilterControllerEvent;

public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
//... // 此处controller可以被该换成任何PHP可回调函数
$event->setController($controller);
}

kernel.view 事件
事件类:GetResponseForControllerResultEvent

FrameworkBundle也不会使用该事件,但是它被用来实现一个视图子系统。该事件只有当Controller不能返回一个Response对象时才被调用。它的目的就是把其他类型的返回值转换成一个Response。

Controller的返回值可以通过getControllerResult方法访问:

use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\Response; public function onKernelView(GetResponseForControllerResultEvent $event)
{
$val = $event->getControllerResult();
$response = new Response();
//通过返回值自定义化Response
$event->setResponse($response);
}

kernel.response 事件
事件类:FilterResponseEvent

该事件的目的是允许其它系统在Response对象被创建后对它进行修改或者替换。

public function onKernelResponse(FilterResponseEvent $event)
{
$response = $event->getResponse();
//修改Response对象
}

FrameworkBundle注册了许多的监听器:

ProfilerListener 从当前请求中搜集数据
        WebDebugToolbarListener 注入Web 调试工具条
        ResponseListener 基于请求的格式来为Response设置Content-type
        EsiListener 当Response需要解析ESI标签时,向其添加一个Surrogate-Control HTTP头。

kernel.exception 事件:
事件类:GetResponseForExceptionEvent
     FrameworkBundle注册一个ExceptionListener把请求定向到一个给定Contoller。这个事件的监听器可以创建和设置一个Response对象,创建设置一个新的Exception对象或者什么都不做。

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response; public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
$response = new Response();
// 基于捕获的异常创建一个Response对象
$event->setResponse($response); // 你可以创建一个新的异常代替原有的
// $exception = new \Exception('Some special exception');
// $event->setException($exception);
}

总结思考:我们了解了Symfony2内部的主要部件和一些主要的事件接口,我们可以在各个事件接口定义相应的监听器处理,来对请求处理过程进行干预操作。

参考URL:http://symfony.com/doc/current/book/internals.html

Symfony2 学习笔记之内部构件的更多相关文章

  1. GIS案例学习笔记-多边形内部缓冲区地理模型

    GIS案例学习笔记-多边形内部缓冲区地理模型 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:对于多边形,建立内部缓冲区. 问题:ArcGIS缓冲工具不支持内部 ...

  2. Symfony2 学习笔记之系统路由

    mfony2 学习笔记之系统路由   漂亮的URL绝对是一个严肃的web应用程序必须做到的,这种方式使index.php?article_id=57这类的丑陋URL被隐藏,由更受欢迎的像 /read/ ...

  3. Symfony2学习笔记之表单

    对于一个Web开发者来说,处理HTML表单是一个最为普通又具挑战的任务.Symfony2集成了一个Form组件,让处理表单变的容易起来.在这一节里,我们将从基础开始创建一个复杂的表单,学习表单类库中最 ...

  4. Symfony2学习笔记之数据库操作

    数据库和Doctrine让我们来面对这个对于任何应用程序来说最为普遍最具挑战性的任务,从数据库中读取和持久化数据信息.幸运的是,Symfony和Doctrine进行了集成,Doctrine类库全部目标 ...

  5. Symfony2 学习笔记之插件格式

    一个bundle类似于其它框架中的插件,但是比插件表现更好.它跟其它框架最主要的不同是在Symfony2中所有东西都是bundle,包括核心框架功能和你写的所有应用程序代码.Symfony2中,bun ...

  6. Symfony2学习笔记之HTTP Cache

    富web应用程序的本质意味着它们的动态.无论你的应用程序多么有效率,每个请求比起静态文件来说总会存在很多的耗费.对于大多数web程序来说,这没什么. Symfony2非常的轻快,无论你做些严重超载的请 ...

  7. Symfony2 学习笔记之服务容器

    现在的PHP应用程序都是面向对象开发,所以主要是由对象构成.有的对象可以方便的分发邮件信息而有的可能帮你把信息写入到数据库中.在你的应用程序中,你可能创建一个对象用于管理你的产品库存,或者另外一个对象 ...

  8. Symfony2 学习笔记之控制器

    一个controller是你创建的一个PHP函数,它接收HTTP请求(request)并创建和返回一个HTTP回复(Response).回复对象(Response)可以是一个HTML页面,一个XML文 ...

  9. Symfony2学习笔记之数据校验

    校验在web应用程序中是一个常见的任务.数据输入到表单需要被校验.数据在被写入数据库之前或者传入一个webservice时也需要被校验. Symfony2 配备了一个Validator 组件,它让校验 ...

随机推荐

  1. sql openxml sp_xml_preparedocument xml 中文乱码

    DECLARE @xmlText xml ,@idoc int set @xmlText = (select doc from openrowset(bulk 'C:\Word\SRC\WebApp\ ...

  2. 重温《js权威指南》 第4、5、6章

    第四章 表达式和运算符         4.2 对象和数组的初始化表达式                数组: []   [3,7] [1+2,3+4] [[1,2,3,],[4,5,6],[7,8, ...

  3. WordPress主题制作教程4:调用指定页面内容

    假设页面page_id=86 $page_id = 86; echo "标题:".get_post($page_id)->post_title; echo "内容: ...

  4. 【重走Android之路】【开篇】序

    [重走Android之路][开篇]   [序]         本人Nodin,偶尔也叫MoNodin,朋友们都喜欢叫我丁,还有个笔名叫陌上幽人,文艺时叫恋风,发奋时叫不肯腐烂的土壤...也许你觉得我 ...

  5. Java:多态性

    Java的多态性:发送消息给某个对象,让该对象自行决定响应何种行为. 通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用. java的多态性要满足三个条件: 1.继承关系 2.在子类重写父类的 ...

  6. iOS:实现MKAnnotation协议,在地图上设置大头针,点击显示具体的位置信息

    如何添加大头针(地标): 通过MapView的addAnnotation方法可以添加一个大头针到地图上 通过MapView的addAnnotations方法可以添加多个大头针到地图上 –(void)a ...

  7. Android addRule()

    布局中有很多特殊的属性,通常在载入布局之前,在相关的xml文件中进行静态设置即可. 但是,在有些情况下,我们需要动态设置布局的属性,在不同的条件下设置不同的布局排列方式,这时候就需要用到 Relati ...

  8. UITableView的使用及性能优化

    UITableView可谓是日常开发中最重要的控件之一,而使用UITableView最重要的在于性能优化.iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITa ...

  9. IMP导入数据 报错 IMP-00058 ORA-01691 IMP-00028

    查看导入日志,发现错误如下: oracle@sspt:/back/log> cat imp.HD_HDXX.log Connected to: Oracle Database 11g Enter ...

  10. 《Linux内核设计与实现》读书笔记(七)- 中断处理【转】

    转自:http://www.cnblogs.com/wang_yb/archive/2013/04/19/3030345.html 中断处理一般不是纯软件来实现的,需要硬件的支持.通过对中断的学习有助 ...