從symfony框架到一個完整的項目需要幾步? (三) 入口文件都做了什麼

前言

對於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'
        ...
    );
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章