これは、symfony アプリケーションをどのように整理するか、そして可能な限りドメイン指向のコードを書く方法を説明するために作成することにしたシリーズの最初の投稿です。
以下に、シリーズのすべてのパートで使用するフロー図を示します。各投稿では、図の具体的な部分に焦点を当て、関係するプロセスを分析し、どの部分が私たちのドメインに属するのか、また外部レイヤーを使用して他の部分から切り離す方法を検出しようとします。
この最初のパートでは、データの抽出と検証のプロセスに焦点を当てます。データ抽出プロセスでは、リクエスト データが JSON 形式で提供されると想定します。
リクエスト データが JSON リクエスト ペイロード内に含まれることがわかっているという事実に基づくと、リクエスト ペイロードの抽出 (この場合、抽出とは JSON ペイロードから配列を取得することを意味します) は、php の json_decode 関数を使用するのと同じくらい簡単です。
class ApiController extends AbstractController { #[Route('/api/entity', name: 'api_v1_post_entity', methods: ['POST'])] public function saveAction(Request $request,): JsonResponse { $requestData = json_decode($request->getContent(), true); // validate data } }
データを検証するには、次の 3 つの要素が必要です。
最初の方法では、受信データを表す DTO (データ転送オブジェクト) を作成し、Symfony 検証制約属性を使用してこのデータを検証する方法を指定します。
readonly class UserInputDTO { public function __construct( #[NotBlank(message: 'Email cannot be empty')] #[Email(message: 'Email must be a valid email')] public string $email, #[NotBlank(message: 'First name cannot be empty')] public string $firstname, #[NotBlank(message: 'Last name cannot be empty')] public string $lastname, #[NotBlank(message: 'Date of birth name cannot be empty')] #[Date(message: 'Date of birth must be a valid date')] public string $dob ){} }
ご覧のとおり、最近作成した DTO 内で入力データ検証ルールを定義しました。これらのルールは次のとおりです:
2 つ目では、Symfony ノーマライザー コンポーネントを使用します。これにより、リクエストの受信データを DTO にマッピングできます。
class ApiController extends AbstractController { #[Route('/api/entity', name: 'api_v1_post_entity', methods: ['POST'])] public function saveAction(Request $request, SerializerInterface $serializer): JsonResponse { $requestData = json_decode($request->getContent(), true); $userInputDTO = $serializer->denormalize($requestData, UserInputDTO::class); } }
上に示したように、denormalize メソッドが処理を実行し、1 行のコードで DTO に受信データが入力されます。
最後に、データを検証するために、最近非正規化された DTO (受信データを運ぶ) のインスタンスを受け取り、DTO ルールに従ってデータを検証する Symfony バリデーター サービスに依存します。
class ApiController extends AbstractController { #[Route('/api/entity', name: 'api_v1_post_entity', methods: ['POST'])] public function saveAction(Request $request,): JsonResponse { $requestData = json_decode($request->getContent(), true); // validate data } }
これまで、抽出とデータの検証のプロセスを 4 つの部分に分割してきました。
ここでの質問は、次のどの部分が私たちのドメインに属しているのかということです。
質問に答えるために、関連するプロセスを分析してみましょう:
1.- データの抽出: この部分では、「json_decode」関数のみを使用して、受信データを json から配列に変換します。ビジネス ロジックは追加されないため、これはドメインに属しません。
2.- DTO: DTO には、入力データに関連付けられたプロパティとその検証方法が含まれます。これは、DTO にビジネス ルール (検証ルール) が含まれているため、DTO がドメインに属することを意味します。
3.- データの非正規化: この部分は単にインフラストラクチャ サービス (フレームワーク コンポーネント) を使用して、データをオブジェクトに非正規化します。これにはビジネス ルールが含まれていないため、これは私たちのドメインに属しません。
4.- データの検証: データの非正規化 プロセスと同じ方法で、データ検証プロセスでもインフラストラクチャ サービス (フレームワーク コンポーネント) を使用して受信データを検証します。 。これにはビジネス ルールが含まれていません。ビジネス ルールは DTO で定義されているため、ドメインの一部にもなりません。
最後のポイントを分析した後、DTO のみがドメインの一部になると結論付けることができます。では、コードの残りの部分をどうすればよいでしょうか?
個人的には、この種のプロセス (データの抽出、非正規化、検証) をアプリケーション層またはサービス層に組み込むのが好きです。なぜ?、アプリケーション層を紹介しましょう。
つまり、アプリケーション層はオーケストレーションと調整を担当し、ビジネス ロジックはドメイン層に任せます。さらに、ドメイン層と、プレゼンテーション層 (UI) やインフラストラクチャ層などの外部層との間の仲介者として機能します。
上記の定義から始めて、抽出、非正規化、および 検証 プロセスをアプリケーション層のサービスに含めることができます。次の理由からです。
完璧です。このプロセスを管理するアプリケーション サービスを作成します。どうやってやろうか?責任をどのように管理するのでしょうか?
単一責任原則 (SRP) は、各クラスがアプリケーションの動作の 1 つの部分のみに対して責任を負うべきであると規定しています。クラスに複数の責任がある場合、理解、維持、変更がより困難になります。
これは私たちにどのような影響を与えますか?それを分析してみましょう。
これまでのところ、アプリケーション サービスは受信データを抽出、非正規化、検証する必要があることがわかっています。これを理解すると、次の責任を簡単に抽出できます:
これらの責任を 3 つの異なるサービスに分割する必要がありますか?そうは思いません。説明しましょう。
これまで見てきたように、各責任はインフラストラクチャ機能またはコンポーネントによって管理されます。
アプリケーション サービスはこれらの責任をインフラストラクチャ サービスに委任できるため、より抽象的な責任 (データの処理) を作成し、それをアプリケーション サービスに割り当てることができます。
class ApiController extends AbstractController { #[Route('/api/entity', name: 'api_v1_post_entity', methods: ['POST'])] public function saveAction(Request $request,): JsonResponse { $requestData = json_decode($request->getContent(), true); // validate data } }
上に示したように、DataProcessor アプリケーション サービスは、json_decode 関数と Symfony のノーマライザーおよびバリデータ サービスを使用して入力リクエストを処理し、新しく検証された DTO を返します。したがって、DataProcessor サービスは次のようになります。
お気づきかと思いますが、検証プロセスでエラーが見つかった場合、DataProcessor サービスは Symfony ValidationException をスローします。このシリーズの次回の投稿では、ビジネス ルールを適用してエラーを構造化し、最終的にクライアントに提示する方法を学びます。
DataProcessor サービスを削除し、MapRequestPayload をサービス アプリケーション層として使用して、データの抽出、非正規化、検証を行うことができることはわかっていますが、この記事の文脈を考えると、より便利だと思いました。このように書いてください。
この最初の記事では、フロー図からのデータの抽出と検証のプロセスに焦点を当てました。このプロセスに含まれるタスクをリストし、どの部分がドメインに属しているかを検出する方法を学びました。
どの部分がドメインに属しているかを把握して、ドメインがルールを定め、データの抽出と検証のプロセスを調整するインフラストラクチャ サービスを接続するアプリケーション層サービスを作成しました。
次の記事では、例外を管理するためのビジネス ルールを定義する方法を検討し、入力 DTO を永続的なエンティティに変換する役割を担うドメイン サービスも作成します。
以上が焦点を絞ったドメイン アプリケーションの作成。 Symfony のアプローチ (パート 1)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。