工廠模式

簡介

如同 services 一樣,工廠( Factories )模式是自動載入的一種延伸,它有助於維持程式碼的簡潔,不必在類別之間傳遞物件實體。簡單來說,工廠模式提供了新建實體後從任何地方存取它的方法。這是一種能夠重複使用物件狀態以減少記憶體負載,並保持多個實體在應用程式中載入的好方式。

任何物件都可以被工廠載入,但最好的使用場景是處理那些用於傳輸普通資料的類別。CodeIgniter 本身也使用了工廠模式,使 Config 類別總是能載入正確的組態設定。

Models 為例,你可以使用工廠類別中的魔術靜態方法 Factories::models() 來存取 Models 的特定工廠。由於命名空間和資料夾有著相同的路徑結構,工廠了解模型檔案與類別被歸類在 Models 資料夾下,所以你可以透過名稱直接向工廠請求一個模型的載入:

use CodeIgniter\Config\Factories;

$users = Factories::models('UserModel');

或是你也可以請求一個特定的類別

$widgets = Factories::models('Some\Namespace\Models\WidgetModel');

無論在何處請求相同的類別時, Factories 都會確保你取得取得一模一樣的實體。

class SomeOtherClass
{
    $widgets = Factories::models('WidgetModel');
    // ...
}

參數

你能夠將控制可選功能的陣列傳入 Factories 的第二個參數,你所傳入的設定將會覆蓋預設的選項。

同時你也能緊接著傳入更多參數,這些參數將被轉送到類別的建構函數中,方便你從外部初始化你的類別。例如:假設你的應用程式使用獨立資料庫進行身分認證,並且你希望任何存取使用者紀錄的行為總是使用特定的連線進行時:

$conn  = db_connect('AuthDatabase');
$users = Factories::models('UserModel', [], $conn);

現在,每當 UserModelFactories 載入時,它都會回傳類別實體,並使用你所希望的資料庫連線。

可選設定

預設的載入模式可能不適合每個元件,例如:你的元件名稱與它的路徑不一致,或者是你需要將實體限制為特定類型的類別上。每個元件可能都需要特定的可選設定來指揮 Factories 探索與實體化。

Key 型別 說明 預設值
component string or null 元件的名稱(如果與靜態方法不同)。替一個元件別名為另一個元件。 null (預設元件名稱)
path string or null 命名空間/資料夾內查找類的相對路徑。 null (預設元件名稱)
instanceOf string or null 所需的類別名稱,以確認回傳的實體。 null (不過濾)
getShared boolean 回傳一個共用實體還是載入一個新實體。 true
preferApp boolean 若是在 App 命名空間中具有相同基本名稱的類別,是否優先於其他明確的請求。 true

行為

可以透過下列三種方式應用可選設定(按照優先級列出):

  • 帶有元件屬性的組態設定檔案 Factory
  • 靜態方法 Factories::setOptions
  • 在呼叫時直接透過參數傳遞可選設定

組態設定

要設定預設的元件選項,請在 app/Config/Factory.php 中建立一個成員變數,並命名為元件名稱。這個變數為一個鍵值陣列,你可以宣告你所需要的可選設定內容。例如:如果你想要保證你的應用程式使用的所有過濾器都是有效的框架實體,你的 Factories.php 可能看起來會像這樣:

<?php

namespace Config;

use CodeIgniter\Config\Factory as BaseFactory;
use CodeIgniter\Filters\FilterInterface;

class Factories extends BaseFactory
{
    public $filters = [
        'instanceOf' => FilterInterface::class,
    ];
}

如果某個模組碰巧在命名空間中擁有一個不相關的「Filters」路徑,這將防止第三方模組發生衝突。

setOptions 方法

Factories 類別提供一個靜態方法,它能夠在執行期間進行可選設定的配置,只需要將設定用的鍵值陣列傳入 setOptions() ,它們將會與預設值合併並儲存以供下一個呼叫

Factories::setOptions('filters', [
    'instanceOf' => FilterInterface::class,
    'prefersApp' => false,
]);

參數傳遞

Factories 的魔術靜態呼叫允許你將可選設定作為第二個參數傳入。這些指令將會覆蓋每個元件的可選設定,並且可以在呼叫時使用以準確的獲得你所需要的內容。你應該要傳入一個陣列,其中的鍵為選項名稱,其值將會覆蓋預設設定。

舉個例子,在預設的情況下, Factories 會假設你所需要的元件是共用實體。透過傳入第二個參數至魔術靜態呼叫中,你可以控制該次呼叫是回傳新實體還是共用實體:

$users = Factories::models('UserModel', ['getShared' => true]); // 預設;; 將永遠為相同實體
$other = Factories::models('UserModel', ['getShared' => false]); // 將永遠建立新的實體