Laravel 之 Application---實踐篇

dongyuhappy發表於2017-03-10

作為容器使用方法

在《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 協議》,轉載必須註明作者和本文連結

相關文章