跳到內容

如何使用配置器設定服務

編輯此頁面

服務*配置器*是服務容器的一項功能,可讓您在服務實例化後,使用可呼叫的物件來設定服務。

例如,當您的服務需要根據來自不同來源/服務的設定進行複雜設定時,可以使用服務配置器。使用外部配置器,您可以保持服務實作的整潔,並使其與提供所需設定的其他物件保持解耦。

另一個使用案例是當您有多個物件共享通用設定,或應該在運行時以類似方式設定時。

例如,假設您有一個應用程式,您可以在其中向使用者發送不同類型的電子郵件。電子郵件會透過不同的格式器傳遞,這些格式器可能會根據某些動態應用程式設定啟用或停用。您開始像這樣定義一個 NewsletterManager 類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Mail/NewsletterManager.php
namespace App\Mail;

class NewsletterManager implements EmailFormatterAwareInterface
{
    private array $enabledFormatters;

    public function setEnabledFormatters(array $enabledFormatters): void
    {
        $this->enabledFormatters = $enabledFormatters;
    }

    // ...
}

以及一個 GreetingCardManager 類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Mail/GreetingCardManager.php
namespace App\Mail;

class GreetingCardManager implements EmailFormatterAwareInterface
{
    private array $enabledFormatters;

    public function setEnabledFormatters(array $enabledFormatters): void
    {
        $this->enabledFormatters = $enabledFormatters;
    }

    // ...
}

如前所述,目標是在運行時根據應用程式設定設定格式器。為此,您還有一個 EmailFormatterManager 類別,負責載入和驗證應用程式中啟用的格式器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/Mail/EmailFormatterManager.php
namespace App\Mail;

class EmailFormatterManager
{
    // ...

    public function getEnabledFormatters(): array
    {
        // code to configure which formatters to use
        $enabledFormatters = [...];

        // ...

        return $enabledFormatters;
    }
}

如果您的目標是避免將 NewsletterManagerGreetingCardManagerEmailFormatterManager 耦合,那麼您可能需要建立一個配置器類別來設定這些實例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/Mail/EmailConfigurator.php
namespace App\Mail;

class EmailConfigurator
{
    public function __construct(
        private EmailFormatterManager $formatterManager,
    ) {
    }

    public function configure(EmailFormatterAwareInterface $emailManager): void
    {
        $emailManager->setEnabledFormatters(
            $this->formatterManager->getEnabledFormatters()
        );
    }

    // ...
}

EmailConfigurator 的工作是將啟用的格式器注入到 NewsletterManagerGreetingCardManager 中,因為它們不知道啟用的格式器來自哪裡。另一方面,EmailFormatterManager 掌握了有關啟用的格式器以及如何載入它們的知識,從而保持了單一職責原則。

提示

雖然此範例使用 PHP 類別方法,但配置器可以是任何有效的 PHP 可呼叫物件,包括函式、靜態方法和服務方法。

使用配置器

您可以使用 configurator 選項設定服務配置器。如果您使用的是[預設 services.yaml 設定](../service_container.html#service-container-services-load-example),則所有類別都已載入為服務。您只需要指定 configurator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# config/services.yaml
services:
    # ...

    # Registers all 4 classes as services, including App\Mail\EmailConfigurator
    App\:
        resource: '../src/*'
        # ...

    # override the services to set the configurator
    App\Mail\NewsletterManager:
        configurator: ['@App\Mail\EmailConfigurator', 'configure']

    App\Mail\GreetingCardManager:
        configurator: ['@App\Mail\EmailConfigurator', 'configure']

服務可以透過可調用配置器(將 configure() 方法替換為 __invoke())進行設定,方法是省略方法名稱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# config/services.yaml
services:
    # ...

    # registers all classes as services, including App\Mail\EmailConfigurator
    App\:
        resource: '../src/*'
        # ...

    # override the services to set the configurator
    App\Mail\NewsletterManager:
        configurator: '@App\Mail\EmailConfigurator'

    App\Mail\GreetingCardManager:
        configurator: '@App\Mail\EmailConfigurator'

就是這樣!當請求 App\Mail\NewsletterManagerApp\Mail\GreetingCardManager 服務時,建立的實例將首先傳遞給 EmailConfigurator::configure() 方法。

本作品,包括程式碼範例,均根據 [Creative Commons BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/) 授權條款授權。
目錄
    版本