前回の投稿では、シリアライザーとバリデーターの symfony コンポーネントが、アプリケーションで一般的なタスクを実行するのに役立つツールを提供するインフラストラクチャー・サービスとしてどのように機能するかを分析しました。また、ビジネス ルールが含まれているため、UserInputDTO クラスがドメインに属する要素である理由と、データ フローの抽出と検証を実行するアプリケーション層サービスの作成方法についても学びました。
この 2 番目のパートでは、検証エラーを管理する方法を説明し、最初のパートと同様に、ドメインに属する部分を特定します。
検証エラーは、検証制約を使用して確立されたルールに従って UserInputDTO を検証した後、Symfony バリデーターコンポーネントによって返されます。
public function processData(string $content, string $dtoClass): object { $requestData = json_decode($content, true); $userInputDTO = $serializer->denormalize($requestData, UserInputDTO::class); $errors = $validator->validate($userInputDTO); if(count($errors) > 0) { throw new ValidationFailedException($errors); } return $userInputDTO }
上記のコードでわかるように、検証メソッドでエラーが検出された場合、ValidationException タイプの例外がスローされます。ここから、ユーザーにエラーをどのように表示するか (ドメイン/ビジネス ルール)、エラーがユーザーに正しく届くようにどのツールに依存するか (インフラストラクチャとアプリケーション) を決定する必要があります。
最初に考慮しなければならないのは、検証エラーが発生するたびにそれを捕捉したいということです。これを達成するには、インフラストラクチャ層に依存します。
Symfony カーネルには、特別なイベントをリッスンするための一連の組み込みカーネル イベントが付属しています。このイベントの 1 つは、例外がスローされたときにトリガーされるカーネル例外イベントです。 ValidationException エラーを捕捉するためにこれを使用してみましょう。
class KernelSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ KernelEvents::EXCEPTION => 'onException' ]; } public function onException(ExceptionEvent $event): void { $exception = $event->getThrowable(); if($exception instanceof ValidationFailedException){ // Business rules to build the errors } } }
上記のコードでわかるように、KernelSubscriber は KernelException イベントをリッスンし続け、キャッチされた例外が ValidationFailedException クラス.
ここからは、
onException メソッドが検証エラーであることを検出したときに実行されるロジックを定義する必要があります。
class ValidationErrorsBuilder { public function buildErrors(ValidationFailedException $exception): array { $errors = []; foreach ($exception->getViolations() as $violation) { $errors[$violation->getPropertyPath()] = $violation->getMessage(); } return $errors; } }
ValidationErrorsBuilder コードは非常に単純です。違反エラーをループし、キーがエラーを生成したプロパティ、値がエラー メッセージである連想配列を作成します。
今度は、ValidationErrorsBuilder ドメイン サービスを使用します。 KernelSubscriber onException メソッドで使用しています。
public function processData(string $content, string $dtoClass): object { $requestData = json_decode($content, true); $userInputDTO = $serializer->denormalize($requestData, UserInputDTO::class); $errors = $validator->validate($userInputDTO); if(count($errors) > 0) { throw new ValidationFailedException($errors); } return $userInputDTO }
ご覧のとおり、例外が ValidationFailedException であることがわかった後、ドメイン サービスを使用して検証エラー配列を取得します。
それでは、次のコードを見てみましょう:
class KernelSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ KernelEvents::EXCEPTION => 'onException' ]; } public function onException(ExceptionEvent $event): void { $exception = $event->getThrowable(); if($exception instanceof ValidationFailedException){ // Business rules to build the errors } } }
エラー配列を保持する Symfony JsonResponse を新しい応答として設定し、返される HTTP コードが 400 Bad Request になることを指定する新しい行を追加しました。
応答 HTTP コードを指定するには、Symfony 応答 HTTP_BAD_REQUEST 定数を利用してきました。ドメイン中心の環境で作業しているため、カスタム ドメイン クラス (例: php enum) を作成することもできますが、標準の HTTP コードを処理するだけでよく、特にカスタマイズする必要がないため、 Symfony HTTP コードですが、これによりフレームワークにもう少し依存することになります。
これまでアプリケーション層については話してきませんでした。記事の冒頭で、Symfony フレームワークには、私たちが使用したカーネル例外イベントなどの便利な組み込みイベントが付属していると述べました。さらに、symfony フレームワークは、カスタム イベント サブスクライバーを作成し、必要なイベントをリッスンできる EventSubscriberInterface も提供します。
この情報から、symfony はカーネル例外イベントと EventSubscriberInterface を提供しますが、どのイベントをリッスンするかを指定するサブスクライバーを作成するにはインターフェースを使用する必要があると結論付けることができます。再開しましょう:
これに聞き覚えはありますか?はい、イベント サブスクライバーは、例外がスローされた後の検証エラーの管理のオーケストレーションと調整を担当するため、イベント サブスクライバーはアプリケーション サービスとして機能すると言えます。
さらに一歩進めたい場合は、アプリケーション層サービスを作成し、それをサブスクライバで使用することもできます。
class ValidationErrorsBuilder { public function buildErrors(ValidationFailedException $exception): array { $errors = []; foreach ($exception->getViolations() as $violation) { $errors[$violation->getPropertyPath()] = $violation->getMessage(); } return $errors; } }
public function onException(ExceptionEvent $event): void { $exception = $event->getThrowable(); if($exception instanceof ValidationFailedException){ $errors = $this->validationErrorsBuilder->buildErrors($exception); } }
ValidationErrorsProcessor は、検証エラー応答管理を調整し、ValidationErrorsBuilder ドメイン サービスを使用するアプリケーション サービスとして機能します。
このシリーズの 2 回目の記事では、検証エラー管理プロセスのどのコンポーネントがドメインに属しているか、使用したインフラストラクチャのどの要素か、カーネル サブスクライバがアプリケーション サービスとしてどのように動作できるかを特定しました。
次の記事では、エンティティをデータベースに永続化し、DTO を永続化可能なエンティティに変換するロジックを分離する方法を分析します。
以上が焦点を絞ったドメイン アプリケーションの作成。 Symfony のアプローチ (検証エラーの管理)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。