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界面发 ...
随机推荐
- Python语言100例
Python版本:python 3.2.2 电脑系统:win7旗舰 实例来源:python菜鸟教程100例 #!/usr/bin/python # -*- coding: UTF-8 -*- impo ...
- redis unwatch discard
UNWATCH UNWATCH 取消 WATCH 命令对所有 key 的监视. 如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行UNWATC ...
- OpenStack overview 笔记
Example architecture example architecture 至少需要两个节点启动一个虚拟机或者实例.可选的服务,例如Block storage和Object storage需要 ...
- js立即执行函数: (function ( ){...})( ) 与 (function ( ){...}( )) 有区别?
没有区别. 你需要明白 IIFE 的原理,我简单说一下: function foo() {...} // 这是定义,Declaration:定义只是让解释器知道其存在,但是不会运行. foo(); / ...
- 如何解决python中urlopen超时问题
看代码: 利用urlopen中的超时参数设立一个循环 while True: try: page = urllib.request.urlopen(url, timeout=3) break exce ...
- map学习笔记
collection是单列集合,map是双列集合.其中包含<k,v>键值对,注意:键具有唯一性,而值不唯一. 在此列举三个读取方式:keyset,valueset,及entryset. k ...
- java 21 - 14 Properties类
类 Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载.属性列表中每个键及其对应值都是一个字符串. 注意:Properties是Has ...
- 使用javascript获取url中的参数
方法一: //取url参数 var type = request("type") function request() { var query = location.search; ...
- HTML5-WebSocket技术学习(2)
上一篇介绍了websocket的基本用法.这篇介绍websocket的一个框架: socket.io socket.io是一个既可以用在客户端又可以用在服务器端的框架. 本篇介绍socket.io在客 ...
- 【转】【C#】异常类 Exception 枚举所有类型的异常
一.基础 在C# 里,异常处理就是C# 为处理错误情况提供的一种机制.它为每种错误情况提供了定制的处理方式,并且把标识错误的代码与处理错误的代码分离开来. 对.NET类来说,一般的 异常类System ...