如何使用配置器設定服務
服務*配置器*是服務容器的一項功能,可讓您在服務實例化後,使用可呼叫的物件來設定服務。
例如,當您的服務需要根據來自不同來源/服務的設定進行複雜設定時,可以使用服務配置器。使用外部配置器,您可以保持服務實作的整潔,並使其與提供所需設定的其他物件保持解耦。
另一個使用案例是當您有多個物件共享通用設定,或應該在運行時以類似方式設定時。
例如,假設您有一個應用程式,您可以在其中向使用者發送不同類型的電子郵件。電子郵件會透過不同的格式器傳遞,這些格式器可能會根據某些動態應用程式設定啟用或停用。您開始像這樣定義一個 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;
}
}
如果您的目標是避免將 NewsletterManager
和 GreetingCardManager
與 EmailFormatterManager
耦合,那麼您可能需要建立一個配置器類別來設定這些實例
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
的工作是將啟用的格式器注入到 NewsletterManager
和 GreetingCardManager
中,因為它們不知道啟用的格式器來自哪裡。另一方面,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\NewsletterManager
或 App\Mail\GreetingCardManager
服務時,建立的實例將首先傳遞給 EmailConfigurator::configure()
方法。