laravel源碼分析之--Application 實例化

這個要啓用後面很長一段時間來解析一下laravel源碼,固然這也是一個浩大工程。可能至少要好幾個月。固然這也是一個很好的學習機會php

前提

我是基於laravel5.4.30+php7.1+maclaravel

laravel 單入口文件

如今全部的框架都基於單入口,那麼laravel框架的但入口文件在哪呢,固然public/index.php,那麼簡單來看一下這個文件bootstrap

//composer 這個也是一個大塊頭,暫時只要知道他能夠自動加載類庫就能夠了,後面單獨在分析
require __DIR__.'/../bootstrap/autoload.php';

//這個地方就是實例化Application 的過程
$app = require_once __DIR__.'/../bootstrap/app.php';

... 
//後面代碼省略

那麼咱們看一下bootstrap/app.php這個文件,代碼:數組

//爲laravel建立了一個實例容積,之後的laravel 的全部主見都會放在這個實例容器裏
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

Illuminate\Foundation\Application繼承Illuminate\Container\Container,這個有什麼用呢,後面看,簡單看一下Application:php7

//構造函數
  public function __construct($basePath = null)
    {
        //註冊一堆框架的目錄,最後都會變成$this->instances 裏面的東西,如圖一
        if ($basePath) {
            $this->setBasePath($basePath);
        }
         //把application 本身綁定到本身的變量$instances中
        $this->registerBaseBindings();
        
        //註冊框架一些基層服務

        $this->registerBaseServiceProviders();
        //註冊核心類的別名

        $this->registerCoreContainerAliases();
    }
    
     //註冊app
      protected function registerBaseBindings()
    {
        //上面說了Application 繼承了Container這個使用了static::,靜態延遲綁定,說面這個方法在Container 裏,這個方法其實就是把Application 實例賦值到 static::$instance 
        static::setInstance($this);

       //註冊一個實例到容器中,這個就變成了 $this->instances['app']=application實例
        $this->instance('app', $this);
       //這個其實和上面也是一下的,$this->instances['"Illuminate\Container\Container"]=Application 實例
        $this->instance(Container::class, $this);
    }
    
       /**
       * 綁定實例到容器中的instances 中
       */
        public function instance($abstract, $instance)
    {

        $this->removeAbstractAlias($abstract);

        $isBound = $this->bound($abstract);

        unset($this->aliases[$abstract]);

        $this->instances[$abstract] = $instance;

        if ($isBound) {
            $this->rebound($abstract);
        }
    }

clipboard.png
【圖一】
其實在__construct有四個步驟:app

  • 註冊全局路徑composer

  • 註冊自身框架

  • 註冊基層服務ide

  • 註冊別名
    其實註冊基層服務重點函數

基層服務

咱們看一下 $this->registerBaseServiceProviders()這個步驟幹了什麼:

/**
    * 綁定全部的基礎服務
   */
  protected function registerBaseServiceProviders()
    {
        //註冊事件服務
        $this->register(new EventServiceProvider($this));
         //日誌服務
        $this->register(new LogServiceProvider($this));
         //路由服務,這個裏面註冊了不少東西,從圖二能夠看出來,路由之後單獨分析
        $this->register(new RoutingServiceProvider($this));
        //最後他們的實例都在 $this->bindings 裏面, 如圖二
    }
    
   
    public function register($provider, $options = [], $force = false)
    {

        ....
         //能夠看到這個地方隨帶啓動上面幾個 服務的 `register` 方法
        if (method_exists($provider, 'register')) {
            $provider->register();
        }
           //把註冊的服務放到$this->serviceProviders 並在$this->loadedProviders 中標記,保證下一次不會重新註冊
          $this->markAsRegistered($provider);
      ....
    }
    
     protected function markAsRegistered($provider)
    {
        $this->serviceProviders[] = $provider;

        $this->loadedProviders[get_class($provider)] = true;
    }

clipboard.png

接下來就是$this->registerCoreContainerAliases(),看下代碼:

public function registerCoreContainerAliases()
    {
      //仔細看一下,這些數據就會一個有規律,數組都是接口和這個接口實例,這也就是laravel 裏的contracts
        foreach ([
            'app'                  => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class],
           //..... 省略
           
        ] as $key => $aliases) {
            foreach ($aliases as $alias) {
                $this->alias($key, $alias);
            }
        }
    }
      //能夠看到這些類的
     public function alias($abstract, $alias)
    {
        $this->aliases[$alias] = $abstract;  //如圖三

        $this->abstractAliases[$abstract][] = $alias;  //如圖四
    }

clipboard.png
【圖三】
clipboard.png
【圖四】

以後返回了一個Application 實例,這一步算是完成了,也就是說bootstrap/app.php 的第一行代碼就是本文的內容了,固然熟悉laravel 的朋友可能看出來,我把serverProvider中的boot給漏掉了,那是由於那裏設計到php的反射,那也是能夠單獨拿出來的一個版塊,後面再說

clipboard.png

相關文章
相關標籤/搜索