作為容器使用方法
在《Application理論篇》中介紹過,它作為容器提供了兩個主要的功能:
- 註冊建立物件的規則,並在需要的時候建立它;
- 提供了類似全域性變數儲存資料的能力。
它的基本使用步驟是:
- 向容器註冊生成物件的規則
- 從容器裡面獲取物件
註冊構建物件的規則
有兩種方式向容器註冊生成物件的規則
- 指定要類的地址,這種方式有問題問題,如果類的建構函式的引數是基本資料型別的話,容器無法注入這部分資料,會發導致建立失敗
-
指定一個閉包函式,具體建立類的邏輯,可以在閉包函式中定義,最終只需要返回建立的物件。
ServiceProvider
中被大量使用。class Car{ protected $name; public function __construct(\Illuminate\Foundation\Application $app, $name) { $this->name = $name; // $app } function __toString() { return (string)$this->name; } } class Something{ } $app = new \Illuminate\Foundation\Application(); // 使用閉包定義建立物件的規則 $app->bind('car',function()use($app){ return new Car($app,'雷克薩斯'); }); // 使用類名的方式 $app->bind('something',Something::class);
共享物件
有些時候,我們在希望在應用程式執行的過程中,物件只被建立一次。
class Car{ protected $name; public function __construct(\Illuminate\Foundation\Application $app, $name) { $this->name = $name; // $app } function __toString() { return (string)$this->name; } } class Something{ } $app = new \Illuminate\Foundation\Application(); // 使用閉包定義建立物件的規則 $app->bind('car',function()use($app){ return new Car($app,'雷克薩斯'.mt_rand(1,100)); }); $app->singleton('car_singleton',function()use($app){ return new Car($app,'雷克薩斯'.mt_rand(1,100)); }); $range = range(1,5); echo "===============car================\r\n"; foreach ($range as $v){ echo $app->make('car')."\r\n";//每次都會建立新的物件 } echo "===============car_singleton================\r\n"; foreach ($range as $v){ echo $app->make('car_singleton')."\r\n";//物件永遠只有一個 }
儲存資料
一般而言,在應用程式執行的生命週期中,只會存在一個物件。所以可以把全域性性質的資料交由它統一保管。
$app = new \Illuminate\Foundation\Application();
$app->instance('data',[1,2,3]);//資料存入容器中
$data = $app->make('data');// 獲取容器中儲存的資料
提供了應用程式執行需要的基本功能
註冊基礎的服務
先有雞還是先有蛋是未解之謎。但是在larval的Application中,它是最先被建立的物件,它自身執行了一些基礎服務的構建。
具體包括
- 把Application物件自身放入容器中。
$this->instance('app', $this);
- 註冊
EventServiceProvider
服務,事件(events)系統是laravel根基。 - 註冊
LogServiceProvider
服務,作為一個成熟的系統,日誌(log)必不可少。 -
註冊
RoutingServiceProvider
系列服務,請求被轉發給具體的處理控制器的規則,就是由這系列服務控制的。提供註冊和執行
ServerProdiver
的功能ServerProdiver
(服務提供者)有下面幾個特徵:- 建構函式有一個Application型別的引數,通常被被儲存在它的屬性裡面
- 必須有一個
register
方法,這個方法通常的作用是向容器裡面註冊一個類構建規則或者一個值 - 可以有一個
boot
方法,用來執行一些初始化操作
在laravel中所有的獨立的功能模組都是以
ServerProdiver
為單位,注入到容器裡面的。提供了設定和獲取專案基本資訊的介面
專案相關的路徑資訊都被注入到了容器中
$this->instance('path', $this->path()); $this->instance('path.base', $this->basePath()); $this->instance('path.lang', $this->langPath()); $this->instance('path.config', $this->configPath()); $this->instance('path.public', $this->publicPath()); $this->instance('path.storage', $this->storagePath()); $this->instance('path.database', $this->databasePath()); $this->instance('path.resources', $this->resourcePath()); $this->instance('path.bootstrap', $this->bootstrapPath()); // 使用 $configPath = app('path.config');// 獲取專案的配置檔案所在目錄 // .................
自定義擴充套件功能
在laravel中,元件內部的一些狀態都是透過事件的形式曝露出來的。例如在執行引導器(bootstraper)的時候
public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);// 派發事件,可以監聽該事件,執行自定義邏輯 $this->make($bootstrapper)->bootstrap($this); $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]); } }
另外一些操作是透過類似hook的方式進行的,例如
afterLoadingEnvironment(Closure $callback)
載入完環境變數後執行的操作無論是透過event的方式還是透過hook的方式進行擴充套件,本質上都是向元件註冊一個回掉函式,元件在合適的時機執行這個回掉函式。
本作品採用《CC 協議》,轉載必須註明作者和本文連結