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界面发 ...
随机推荐
- 实验:sigsuspend(),sigprocmask()
实验:sigsuspend(),sigprocmask() 源代码: /* * Program: pause_suspend.c * To test the difference between si ...
- 探索 OpenStack 之(12):cinder-api Service 处理 HTTP Request 的过程分析
本文是上一篇 探索 OpenStack 之(11):cinder-api Service 启动过程分析 以及 WSGI / Paste deploy / Router 等介绍> 的后续篇. os ...
- 搜索+剪枝 POJ 1416 Shredding Company
POJ 1416 Shredding Company Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5231 Accep ...
- Linux安装Memcached服务
环境: CentOS 6.4 libevent-1.4.14b-stable memcached-1.4.21 查看是否安装libevent[root@localhost ~]# rpm -qa |g ...
- [转]比较Jmeter、Grinder和JAVA多线程本身压力测试所带来的性能开销
1. 测试环境 jmeter版本 :jmeter 2.4 grinder的版本 : Grinder 3 JAVA的版本:JDK 1.6 2. 测试代码 Jmeter测试代码 public class ...
- IO流的练习5 —— 读取文件中的字符串,排序后写入另一文件中
需求:已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl” 请编写程序读取数据内容,把数据排序后写入ss.txt中. 分析: A:读取文件中的数据 B:把数 ...
- man 在线手册
http://man7.org/linux/man-pages/man3/fwrite.3.html
- Pro Git(中文版)
Pro Git(中文版) 返回 Git @ OSC 目录 1.起步 1.1 关于版本控制 1.2 Git 简史 1.3 Git 基础 1.4 安装 Git 1.5 初次运行 Git 前的配置 1.6 ...
- Web 服务编程,REST 与 SOAP(转)
原文地址:Web 服务编程,REST 与 SOAP REST 简介 在开始我们的正式讨论之前,让我们简单看一下 REST 的定义. REST(Representational State Transf ...
- 异步编程 In .NET(转)
转自:http://www.cnblogs.com/jesse2013/p/Asynchronous-Programming-In-DotNet.html 概述 在之前写的一篇关于async和awai ...