ホームページ >バックエンド開発 >PHPチュートリアル >自動接続された Symfony サービスに値オブジェクトを注入する
チームで Symfony プロジェクトに取り組んでいるとき、サービスの 1 つに特定の値オブジェクト インスタンスを挿入する必要がありました。この特定のケースでは、値自体は .env ファイルで提供される値から設定する必要がありました。
もちろん、文字列値をサービスに直接渡して、サービスがコンストラクターで値オブジェクトをインスタンス化できるようにすることもできますが、services.yaml ファイルで設定して注入できるかどうかを確認したかったのです。代わりに、完全にインスタンス化されたオブジェクトが使用されます。これにより、それらのオブジェクト インスタンスを複数のサービスに渡すことができ、それぞれのサービス内で値オブジェクトの作成を繰り返す必要がなくなります。
これが私がやった方法です...
私たちのアプリケーションは Twilio SDK を利用しています。 SDK 呼び出しをラップするさまざまなサービスがあり、それらは環境固有の設定値 (環境ごとの当社の API キーなど) を使用する必要があります。
Twilio API は文字列識別子 (SID) を使用します。 SID の各タイプには、それに関連付けられた異なる 2 文字のプレフィックスがあり、その後に数字 0 ~ 9 と文字 A ~ F (大文字と小文字) で構成される 32 文字が続きます。
例:
各 SID タイプの値オブジェクトが、渡された値にその SID タイプに適切なプレフィックスがあることを検証するとともに、文字列が正しい長さであり、許可されている文字のみで構成されていることを確認したかったのです。 .
私の各 SID タイプは同じ検証ロジックと機能を使用し、SID タイプのプレフィックスによってのみ区別されるため、基本特性を作成することは理にかなっています。必要に応じて、これを抽象クラスにすることもできます。アプリにはパラメータ型などとして TwilioStringIdentifier の概念は必要ないので、ここでは抽象クラスよりもトレイトを好みます。
この特性は、各 SID タイプが実装する必要がある抽象メソッド getPrefixForSidType() を定義し、その特定のタイプに適切なプレフィックスを提供します。また、検証ロジックも実行します。
namespace App\Domain\Model\Twilio\Sid; use Assert\Assert; trait TwilioStringIdentifier { private readonly string $sid; abstract private function getPrefixForSidType(): string; public static function fromString(string $string): self { return new self($string); } public function __construct(string $sid) { Assert::that($sid) ->startsWith($this->getPrefixForSidType()) ->length(34) ->regex('/^[a-zA-Z]{2}[0-9a-fA-F]{32}$/') ; $this->sid = $sid; } public function asString(): string { return $this->sid; } }
各 SID タイプを表す値オブジェクト クラスは単純です。必要なのは、TwilioStringIdentifier Trait を使用し、getPrefixForSidType() メソッドで適切なプレフィックスを定義することだけです。
namespace App\Domain\Model\Twilio\Sid; final readonly class AccountSid { use TwilioStringIdentifier; private function getPrefixForSidType(): string { return 'AC'; } }
他の SID タイプ クラスは、定義されたプレフィックスを除いて同一です。
これらの値オブジェクトはアプリケーション全体で使用され、会社のグローバル値だけでなく、さまざまな値が関連付けられて使用されるため、定義された値ですでにインスタンス化されている特定のタイプのオブジェクトをサービスに注入する方法が必要でした。 .env ファイル
Symfony には、Factory 経由でインスタンス化されるサービスを定義できる機能があることは知っていましたが、他の場所からのメソッド呼び出しの結果であるオブジェクトの注入については、実際に見たことがありませんでした (私の記憶では)。また、これらの Factory メソッドに引数を渡すことができることも知っていましたが、1 つの Value Object インスタンスでこれを行う方法がわかりませんでした。
Symfony のサービス定義では、各サービスに名前を付けることができます。通常、これは Service クラスの名前で行われます:
App\Path\To\My\Service: class: App\Path\To\My\Service arguments: []
ただし、そのサービス名はクラス名と一致する必要はありません。 app.my_service や FooBarBazService などです。
では、必要な値オブジェクトのインスタンス化されたインスタンスである一意の名前を持つサービスを作成したらどうなるでしょうか? .env 値を引数として渡して、そのオブジェクト インスタンスをサービス クラスに注入することができます!
# Create services named with a Global "namespace" Global\Twilio\Sid\Account: factory: ['App\Domain\Model\Twilio\Sid\AccountSid', 'fromString'] arguments: ['%env(TWILIO_ACCOUNT_SID)%'] Global\Twilio\Sid\Api: factory: ['App\Domain\Model\Twilio\Sid\ApiSid', 'fromString'] arguments: ['%env(TWILIO_API_SID)%'] Global\Twilio\Sid\Application: factory: ['App\Domain\Model\Twilio\Sid\ApplicationSid', 'fromString'] arguments: ['%env(TWILIO_APP_SID)%']
次に、それらのサービス (オブジェクト) を名前付き引数を介して Twilio サービスに渡します。
App\Service\Vendor\Twilio\TwilioService: arguments: $accountSid: '@Global\Twilio\Sid\Account' $apiSid: '@Global\Twilio\Sid\Api' $applicationSid: '@Global\Twilio\Sid\Application' $apiSecret: '%env(TWILIO_API_SECRET)%'
これで、私のサービス クラスは、完全にインスタンス化された値オブジェクト インスタンスを受け取ることができるようになりました。
namespace App\Service\Vendor\Twilio; use App\Domain\Model\Twilio\Sid\AccountSid; use App\Domain\Model\Twilio\Sid\ApiSid; use App\Domain\Model\Twilio\Sid\ApplicationSid; final readonly class TwilioService { public function __construct( private AccountSid $accountSid, private ApiSid $apiSid, private ApplicationSid $applicationSid, private string $apiSecret ) {} }
出来上がり!
symfony は十分に柔軟で直観的であるため、これを行う方法を理解するのは簡単でした。これを行うためのクイックリファレンスが他に見つからなかったので、Future Me や同様のことを行う必要がある他の人のためのリファレンスとしてこれを書き留めておこうと思いました
乾杯、コーディングを楽しんでください!
以上が自動接続された Symfony サービスに値オブジェクトを注入するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。