从symfony框架到一个完整的项目需要几步-三-入口文件都做了什么

5次阅读

共计 2817 个字符,预计需要花费 8 分钟才能阅读完成。

前言

对于 php 的框架,无论是 yiisymfony 或者是 laravel,大家都在工作中有涉猎。对于在框架中的存放着资源包vendor 文件夹,入口文件(index.php 或者 app.php),大家也都与他们每天碰面。但是你真的熟悉这些文件 / 文件夹吗?一个完整的项目是如何从一个纯净框架发展而来?各个部分又在框架这个大厦中又起到了怎么样的作用?

三、symfony

总说服务器端删缓存,到底实在删除什么?

3.1 入口文件

...
$loader = require_once __DIR__.'/../app/autoload.php';
require_once __DIR__.'/../app/bootstrap.php.cache';

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$kernel->setRequest($request);
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
...

我们看着这个文件,发现一上来必须将 autoload 文件引入进来。之前的文章讲了大半天,说的就是一个依赖关系文件的问题。我们必须要把这个依赖关系。

下面着重解释一下 AppKernelApplication

先来看一下 AppKernel.php 里面的 boot 方法。这个方法是整个 Appker 类的引导方法,也是核心。它里面做了如下几个工作。

  • 实例化Bundle
  • 实例化容器
  • 实例化 BIZ 类
  • 将每个 Bundle 进行引导
public function boot()
{if (true === $this->booted) {return;}
    if ($this->loadClassCache) {$this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
    }
    /**
     * 实例化 Bundles。*/
    $this->initializeBundles();
    /**
     * 根据 cache/Jianmo/appDevDebugProjectContainer.php.meta 是否存在、该文件内容(序列化)与配置文件内容是否一致
     * 来判断是否需要生成 cache/Jianmo/appDevDebugProjectContainer.php 文件以及相关文件
     * 其中 appDevDebugProjectContainer.php 内容如下
     * 初始化 appDevDebugProjectContainer 类(其中 methodMap 对象是 "类与实例化该类的方法' 对照表)
     * 初始化完成后,调用 $this->>getContainer->get($methodMapClassName)即可以实现对该类的实例化
     */
    $this->initializeContainer();
    /**
     * 调用 appDevDebugProjectContainer->getBizService()方法
     * 实例化 Biz 类
     * 其中的初始化参数由 app/config/biz.yml 提供
     */
    $this->initializeBiz();
    /**
     * AppKernel 是一个重要的文件
     * 无论在 console 命令行模式 / 浏览器请求模式中,都起着至关重要的作用
     * 它是对于 symfony 的 kernel 进行的封装
     * 该方法对于 kernal 进行初始化操作
     */
    $this->initializeServiceKernel();
    foreach ($this->getBundles() as $bundle) {$bundle->setContainer($this->container);
        $bundle->boot();}
    $this->booted = true;
}

3.1.2 实例化 Bundle

3.1.2 实例化容器

这个方法写在 vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php 是一个写在 symfony 中的底层方法,我们要在这里面详细的说一说他的功能、形成。

protected function initializeContainer()
{$class = $this->getContainerClass();
    $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
    $fresh = true;
    if (!$cache->isFresh()) {$container = $this->buildContainer();
        $container->compile();
        $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());

        $fresh = false;
    }

    require_once $cache->getPath();
    /**
     * 对刚刚生成的 app[Dev|Prod]]DebugProjectContainer 类进行实例化。* 我们去看一下该类,会发现在__construct 里面
     */
    $this->container = new $class();
    $this->container->set('kernel', $this);

    if (!$fresh && $this->container->has('cache_warmer')) {$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
    }
}

如果在这个时候我们打开 app/cache/[prod|dev]/Jianmo/app[Dev|Prod]]DebugProjectContainer.php 文件我们就会发现,他在 __construct() 中,将所有的要被加载的类名称和方法都被写到了一个大的数组当中。代码如下,我们如果想要初始化 biz 这个类,只需要调用 getBizService 方法。而这个方法也在当前的文件中。

...
public function __construct()
{
    ...
    $this->methodMap = array(
        'annotation_reader' => 'getAnnotationReaderService',
        'app.locale_listener' => 'getApp_LocaleListenerService',
        'biz' => 'getBizService'
        ...
    );
}

正文完
 0