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对象,发送至客户端,我们就可以看到其内容啦。

时间: 2024-10-25 03:16:21

Symfony启动过程详细学习的相关文章

Centos-----系统启动过程详细叙述

昨日有个前辈问我,liunx系统是如果启动的,我只是说了个大概,但具体的过程没有理解透彻,今天特意在网上找到下面的流程图,并根据图,进行了详细叙述,如有问题,请指出. 启动第一步--加载BIOS  设备加电,首先会加载BIOS信息,BIOS信息很重要.之所以第一个启动,是因BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘信息.内存信息.时钟信息.PnP特性等等.在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了. 启动第二步--读取MBR   众所周知,硬盘上第0磁道第一个扇区被

计算机启动过程详细介绍

全面认识计算机启动过程 首先让我们来了解一些基本概念.第一个是大家非常熟悉的BIOS(基本输入输出系统),BIOS是直接与硬件打交道的底层代码,它为操作系统提供了控制硬件设备的基本功能.BIOS包括有系统BIOS(即常说的主板BIOS).显卡BIOS和其它设备(例如IDE控制器.SCSI卡或网卡等)的BIOS,其中系统BIOS是本文要讨论的主角,因为计算机的启动过程正是在它的控制下进行的.BIOS一般被存放在ROM(只读存储芯片)之中,即使在关机或掉电以后,这些代码也不会消失. 第二个基本概念是

U-Boot启动过程--详细版的完全分析2

一.初识u-boot 3 1,Bootloader介绍 3 2,Bootloader的启动方式 3 (1)网络启动方式 4 (2)磁盘启动方式 4 (3)Flash启动方式 4 3,U-boot的定义 4 4,u-boot源代码的目录结构 4 5,U-boot中的地址 5 (1)什么是编译地址?什么是运行地址? 5 (2)编译地址和运行地址如何来算呢? 5 (3)为什么要分配编译地址?这样做有什么好处,有什么作用? 5 (4)什么是相对地址? 6 (5)如何去做呢? 6 二.U-Boot总体分析

Linux内核分析 实验三:跟踪分析Linux内核的启动过程

贺邦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 一. 实验过程 1.打开shell,输入启动指令,内核启动完成后进入menu程序,支持三个命令help.version和quit. 2.然后使用gdb跟踪调试内核,输入命令qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 3.按住

linux内核启动过程学习总结

下面是学习linux内核启动过程的记录 平台是:powerpc mpc8548 + linux2.6.23 内核 通用寄存器的作用r0 :在函数开始时使用r1 :存放堆栈指针,相当于ia32架构中的esp寄存器r2 :存放当前进程的描述符的地址r3 :存放第一个参数和返回地址r4-r10 :存放函数的参数r11 :用在指针的调用和当前一些语言的环境指针r12 :用于存放异常处理r13 :保留做为系统线程IDr14-r31 :作为本地变量,具有非易失性 Linux启动过程描述 第一步:使用Boot

quick cocos2d x 手机(Android端)启动过程学习

简要学习下quick cocos2d x 在安卓端启动的过程. 首先需要了解一点:quick cocos2d x是依托于Android的activity和GLSurfaceView(继承自SurfaceView)的环境来显示quick层的游戏界面. (1)首先quick类的android游戏从AndroidManifest.xml文件指定的activity(假设AC)启动. (2)AC继承父类的Cocos2dxActivity. (3)调用静态初始化块,加载cocos2dx的动态库.也就是一些C

Android的学习之路(三)项目的启动过程和安装过程详解

应用的安装和启动过程: 安装:第一步:java的编译器会把这个.java文件编译成.class文件 第二部:Android的SDK提供了一个dx工具,这个工具把.class文件转义成.dex文件 第三部:打包操作,把.dex文件和资源文件进行打包,打包成一个压缩文件,然后进行签名.最后就打包成为了.apk文件 第四部:调用adb指令:adb install c:/x.apk安装到模拟器 具体过程:.JAVA---->.class--.dx-->.dex--->打包签名--->.ap

0-Android应用程序的Activity启动过程简要介绍和学习计划

源码分析 之 Activity启动过程简要介绍和学习计划 来源: http://blog.csdn.net/luoshengyang/article/details/6685853 声明: RTFSC(Read the fucking source code)是Linus的名言,也是学习IT技术一个重要手段.学习android最好手段就是对android进行系统分析,关于android系统的源码,CSDN的老罗分析分析是最系统一个.但是老罗的分析源码的blog,有几点不够好: 1.废话太多,可能

Android应用程序的Activity启动过程简要介绍和学习计划

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activity和Service是应用程序的核心组件,它们以松藕合的方式组合在一起构成了一个完整的应用程序,这得益 于应用程序框架层提供了一套完整的机制来协助应用程序启动这些Activity和Service,以及提供Binder机制帮助它们相互间进行通信.在前 面的文章Android进程间通信(IPC)机制B