[CodeIgniter4]概述-服務

Introduction

CodeIgniter中的所有類均作為「服務」提供。這僅意味著,要對要調用的類進行硬定義,而不是對要載入的類名稱進行硬編碼,而是在一個非常簡單的配置文件中定義它們。該文件是一種工廠類型,用於創建所需類的新實例。

一個簡單的示例可能會使事情變得更清楚,因此可以想像您需要引入Timer類的實例。最簡單的方法就是創建該類的新實例:

$timer = new CodeIgniterDebugTimer();

這很棒。直到您決定要使用其他計時器類代替它。也許這有一些高級的報告,默認計時器沒有提供。為此,您現在必須在使用計時器類的應用程式中找到所有位置。由於您可能已將它們留在原處以保持應用程式的性能日誌持續運行,因此這可能是一種耗時且容易出錯的方法。那就是服務派上用場的地方。

我們不用自己創建實例,而是讓中央類為我們創建該類的實例。此類非常簡單。它僅包含我們要用作服務的每個類的方法。該方法通常返回該類的共享實例,並將其可能具有的所有依賴關係傳遞給它。然後,我們將用調用此新類的程式碼替換計時器創建程式碼:

$timer = ConfigServices::timer();

當需要更改所使用的實現時,可以修改服務配置文件,並且更改無需更改即可自動在整個應用程式中進行。現在,您只需要利用所有新功能,就可以了。非常簡單且抗錯誤。

註解

建議僅在控制器內創建服務。其他文件,例如模型和庫,應將依賴項傳遞到構造函數中或通過setter方法傳遞。

方便的功能

提供了兩種功能來獲得服務。這些功能始終可用。

第一個是service()返回所請求服務的新實例。唯一需要的參數是服務名稱。這與Services文件中的方法名稱始終返回該類的SHARED實例相同,因此多次調用該函數應始終返回同一實例:

$logger = service('logger');

如果創建方法需要其他參數,則可以在服務名稱之後傳遞它們:

$renderer = service('renderer', APPPATH.'views/');

第二個函數的single_service()工作原理類似,service()但返回類的新實例:

$logger = single_service('logger');

定義服務

為了使服務正常運行,您必須能夠依賴具有恆定API或介面才能使用的每個類 。幾乎所有CodeIgniter的類都提供了它們遵循的介面。當您要擴展或替換核心類時,只需要確保滿足介面的要求並且知道這些類是兼容的即可。

例如,RouterCollection該類實現RouterCollectionInterface。當您想創建一個提供不同方式創建路由的替代品時,只需創建一個實現以下內容的新類RouterCollectionInterface

class MyRouter implements CodeIgniterRouterRouteCollectionInterface  {          // Implement required methods here.  }

最後,修改/application/Config/Services.php以創建的新實例,MyRouter 而不是CodeIgniterRouterRouterCollection

public static function routes()  {          return new AppRouterMyRouter();  }

允許參數

在某些情況下,您希望該選項在實例化期間將設置傳遞給類。由於服務文件是非常簡單的類,因此輕鬆進行此工作。

renderer服務就是一個很好的例子。默認情況下,我們希望此類能夠在中找到視圖APPPATH.views/。但是,如果開發人員需要,我們希望開發人員可以選擇更改該路徑。因此,該類接受$viewPath 作為構造函數參數。服務方法如下:

public static function renderer($viewPath=APPPATH.'views/')  {          return new CodeIgniterViewView($viewPath);  }

這將在構造方法中設置默認路徑,但允許輕鬆更改其使用的路徑:

$renderer = ConfigServices::renderer('/shared/views');

共享類

在某些情況下,您需要要求僅創建服務的單個實例。getSharedInstance()從工廠方法內部調用的方法很容易處理。這用於檢查實例是否已在類中創建並保存,如果沒有,則創建一個新實例。所有工廠方法都提供一個 值作為最後一個參數。您還應該堅持使用該方法:$getShared = true

class Services  {      public static function routes($getShared = false)      {          if (! $getShared)          {              return new CodeIgniterRouterRouteCollection();          }            return self::getSharedInstance('routes');      }  }

服務發現

CodeIgniter可以自動發現您可能在任何定義的名稱空間中創建的任何ConfigServices.php文件。這樣可以簡單地使用任何模組服務文件。為了發現自定義服務文件,它們必須滿足以下要求:

  • 必須定義名稱空間 ConfigAutoload.php
  • 在名稱空間內,必須在以下位置找到文件 ConfigServices.php
  • 它必須擴展 CodeIgniterConfigBaseService

一個小例子可以澄清這一點。

想像一下,您已經Blog在根目錄中創建了一個新目錄。這將包含一個帶有控制器,模型等的Blog模組,並且您想將某些類作為服務使用。第一步是創建一個新文件: BlogConfigServices.php。該文件的框架應為:

<?php namespace BlogConfig;    use CodeIgniterConfigBaseService;    class Services extends BaseService  {      public static function postManager()      {          ...      }  }

現在,您可以如上所述使用此文件。當您想從任何控制器獲取職位服務時,只需使用框架的ConfigServices類即可獲取服務:

$postManager = ConfigServices::postManager();

註解

如果多個Services文件具有相同的方法名稱,則第一個找到的將是返回的實例。