這個要啓用後面很長一段時間來解析一下laravel源碼,固然這也是一個浩大工程。可能至少要好幾個月。固然這也是一個很好的學習機會php
我是基於laravel5.4.30+php7.1+maclaravel
如今全部的框架都基於單入口,那麼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); } }
【圖一】
其實在__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; }
接下來就是$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; //如圖四 }
【圖三】
【圖四】
以後返回了一個Application 實例,這一步算是完成了,也就是說bootstrap/app.php
的第一行代碼就是本文的內容了,固然熟悉laravel 的朋友可能看出來,我把serverProvider
中的boot
給漏掉了,那是由於那裏設計到php的反射,那也是能夠單獨拿出來的一個版塊,後面再說