Symfony启动过程详细学习
想了解symfony的启动过程,必须从启动文件(这里就以开发者模式)开始。
<?php
/*
* web/app_dev.php
*/
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
Debug::enable();
require_once __DIR__.'/../app/AppKernel.php';
//初始化AppKernel
$kernel = new AppKernel('dev', true);
//Kernel启动后,载入缓存
$kernel->loadClassCache();
//利用一些信息来构造Request对象(如$_GET $_POST等等)
$request = Request::createFromGlobals();
//通过symfony内核将Request对象转化为Response对象
$response = $kernel->handle($request);
//输出Response对象
$response->send();
//执行一些邮件发送等耗时操作
$kernel->terminate($request, $response);
?>
从上述看来,基本思想就是客户端请求,Symfony内核通过执行响应的请求,返回响应的Response对象,那么symfony是如何执行响应的请求呢?下面通过官方文档看下
Incoming requests are interpreted by the routing and passed to
controller functions that return Response objects.Each “page” of your
site is defined in a routing configuration file that maps different URLs
to different PHP functions. The job of each PHP function, called a
controller, is to use information from the request – along with many
other tools Symfony makes available – to create and return a Response
object. In other words, the controller is where your code goes: it’s
where you interpret the request and create a response.
先大致了解一下其工作流程,下面我们来看如何获得Request对象的,在createFromGlobals方法内主要调用createRequestFromFactory方法。
这些参数都是通过http请求后,使用超全局变量self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server);
再通过构造函数实例化一个Request对象返回。
<?php
private static function createRequestFromFactory(array
$query = array(), array $request = array(), array $attributes = array(),
array $cookies = array(), array $files = array(), array $server =
array(), $content = null)
{
if (self::$requestFactory) {
$request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);
if (!$request instanceof self) {throw new \LogicException('The Request
factory must return an instance of
Symfony\Component\HttpFoundation\Request.');
}
return $request;
}
return new static($query, $request, $attributes, $cookies, $files, $server, $content);
}
?>
createRequestFromFactory
顾名思义通过工厂来创建request对象在Request的类中有$requestFactory属性,若通过自己实例化一个Request对象类,再
通过setFactory()函数设置下工厂,即可以通过自定义,否则即static进行实例化。此时返回一个Request对象。
关于上面的 new static(),与new self()的区别。下面是一外国人对其的解释self refers to the same
class whose method the new operation takes place in.static in PHP 5.3
is late static bindings refers to whatever class in the hierarchy which
you call the method on.In the following example, B inherits both methods
from A. self is bound to A because it’s defined in A’s implementation
of the first method, whereas static is bound to the called class (also
see get_called_class() ).
其实通过一个实例就显而易见
<?php
class A {
public static function get_self() {
return new self();
}
public static function get_static() {
return new static();
}
}
class B extends A {}
echo get_class(B::get_self()); // A
echo get_class(B::get_static()); // B
echo get_class(A::get_static()); // A
?>
通过例子很容易就能明白。
在Controller中我们就可以通过Request对象获取相的参数,处理数据后,返回一个Response对象。那么怎样返回一个Response对象呢?
让我们进入$kernel->handle($request);
<?php
/**
* {@inheritdoc}
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
//symfony内核只启动一次
if (false === $this->booted) {
//注册所有的Bundles
//初始化container, 加载、缓存配置数据和路由数据等,
$this->boot();
}
//内核处理请求
return $this->getHttpKernel()->handle($request, $type, $catch);
}
?>
<?php
/**
* Boots the current kernel.
*/
public function boot()
{
if (true === $this->booted) {
return;
}
if ($this->loadClassCache) {
$this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
}
// 里面调用kernel->registerBundles()
$this->initializeBundles();
// 初始化container,包括载入配置信息、编译信息等
//Symfony2的核心组件的加载
$this->initializeContainer();
//将各个bundle注入container,以便能使用其内容
//并启动bundle
foreach ($this->getBundles() as $bundle) {
$bundle->setContainer($this->container);
$bundle->boot();
}
$this->booted = true;
}
?>
<?php
//内核处理请求,下面是主要的信息,就是通过请求,执行相应的controller,渲染view
private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{
$this->requestStack->push($request);
// 请求对象
$event = new GetResponseEvent($this, $request, $type);
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
if ($event->hasResponse()) {return $this->filterResponse($event->getResponse(), $request, $type);
}
// 载入响应的controller
if (false === $controller =
$this->resolver->getController($request)) {throw new
NotFoundHttpException(sprintf('Unable to find the controller for path
"%s". The route is wrongly configured.', $request->getPathInfo()));
}
$event = new FilterControllerEvent($this, $controller, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);
$controller = $event->getController();
// controller的参数
$arguments = $this->resolver->getArguments($request, $controller);
// 调用controller
$response = call_user_func_array($controller, $arguments);
// view
if (!$response instanceof Response) {$event = new
GetResponseForControllerResultEvent($this, $request, $type,
$response);$this->dispatcher->dispatch(KernelEvents::VIEW,
$event);if ($event->hasResponse()) { $response =
$event->getResponse();}if (!$response instanceof Response) { $msg =
sprintf('The controller must return a response (%s given).',
$this->varToString($response)); if (null === $response) { $msg .= '
Did you forget to add a return statement somewhere in your controller?';
} throw new \LogicException($msg);}
}
return $this->filterResponse($response, $request, $type);
}
?>
此时就返回一个Response对象,发送至客户端,我们就可以看到其内容啦。
Symfony启动过程详细学习的更多相关文章
- 【ARM-Linux开发】U-Boot启动过程--详细版的完全分析
---------------------------------------------------------------------------------------------------- ...
- hadoop namenode启动过程详细剖析及瓶颈分析
NameNode中几个关键的数据结构 FSImage Namenode 会将HDFS的文件和目录元数据存储在一个叫fsimage的二进制文件中,每次保存fsimage之后到下次保存之间的所有hdfs操 ...
- Activity 的启动过程深入学习
手机应用也是一个app,每一个应用的icon都罗列在Launcher上,点击icon触发onItemClick事件. 我们要启动「淘宝」这个App,首先我们要在清单文件定义默认启动的Activity信 ...
- 2440nandflash启动过程再学习
2011-02-13 12:27:05 2440nandflash启动,先是nandflash的前4K自动复制到CPU的0x0地址开始的4K区域. 然后CPU开始运行这4K(刚才copy过来的代码), ...
- (一)U-Boot启动过程--详细版的完全分析
博客地址:http://blog.csdn.net/hare_lee/article/details/6916325
- Linux内核分析 实验三:跟踪分析Linux内核的启动过程
贺邦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 一. 实验过程 ...
- Nginx学习笔记(六) 源码分析&启动过程
Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...
- Android应用程序的Activity启动过程简要介绍和学习计划
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...
- openstack学习笔记一 虚拟机启动过程代码跟踪
openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...
随机推荐
- iBus
0.闲言 闲来无事,重新玩玩Ubuntu,于是先把Ubuntu13.04删了(为什么是13.04?我也不知道)翻出14.04U盘安装,还算顺利,就是不知道为什么DiskGenius为什么一直提示分区表 ...
- 通用cube refresh方案
通用cube refresh c# script 解决方法: 需要设置的变量如下: User::varcubename,User::varolapconnstr,User::varolapdbname ...
- [转]jQuery插件实现模拟alert和confirm
本文转自:http://www.jb51.net/article/54577.htm (function () { $.MsgBox = { Alert: function (title, msg) ...
- Selenium2怎么调用selenium1中方法
虽然selenium1.0已经成为过去时,现在都用selenium2.0,但是如果想要在代码中调用selenium1.0的api怎么办,看下面 WebDriver driver = new Chrom ...
- 两道相似KMP题
1.POJ 3450 Coporate Identity 这两题的解法都是枚举子串,然后匹配,像这种题目以后可以不用KMP来做,直接字符串自带的strstr函数搞定,如果字符串未出现,该函数返回NUL ...
- python基础随笔
一: 作用域 对于变量的作用域,只要内存中存在,该变量就可以使用. 二:三元运算 name = 值1 if 条件 else 值2 如果条件为真:result = 值1 如果条件为假:result = ...
- Windows客户端C/C++编程规范“建议”——风格
本文来自:http://blog.csdn.net/breaksoftware/article/details/37935459 命名风格也非常适用于C# 9 风格 9.1 优先使用匈牙利命名法 等级 ...
- usb驱动开发4之总线设备驱动模型
在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...
- C# 调用C++/MFC写的dll
C#调用C++的非托管类的dll其实很简单基本就是固定的调用格式. dll的编写,首先是打开VS新建一个C++的控制台程序,下一步后选择dll以及空文档即可.然后就是添加一个类添加一个方法.方法排头固 ...
- 一份高级Java招聘要求
搜了一些招聘,发现自己还有很长的路要走啊,学无止境...... 摘一个典型的招聘要求,如下: 1.5年基于java的项目开发经验,2.熟悉基于 J2EE的相关开源技术以及Spring,Struts2, ...