zoukankan      html  css  js  c++  java
  • 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是如何执行响应的请求呢?下面通过官方文档看下


    初窥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 SymfonyComponentHttpFoundationRequest.');
    }
    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对象,发送至客户端,我们就可以看到其内容啦。

  • 相关阅读:
    cad是什么意思?教你快速把cad转换成pdf格式
    为什么街上的商贩更喜欢用微信支付,而不是支付宝,看完长知识了
    音乐剪辑软件怎么用?教你一个快速编辑音频的方法
    电脑如何录制视频?安利两种电脑录屏的方法
    被称为逆天改命的5大中国工程,曾轰动世界,你知道几个?
    如何使用音乐格式转换器?快速编辑音频文件的方法
    PPT结尾只会说“谢谢”?学会这些PPT结尾,观众主动为你鼓掌
    经典PHP面试题(冒泡排序),当场就被打脸,卧槽什么冒泡?为啥还排序?
    千万不要再搞混了,函数empty( var );输出的判断值是false : true
    PHP删除数组中空数组
  • 原文地址:https://www.cnblogs.com/phpxuetang/p/5666912.html
Copyright © 2011-2022 走看看