Laravel + Vue.js + DDDのすゝめ – コントローラとフォームバリデーション

Laravel + Vue.js + DDDのすゝめ – コントローラとフォームバリデーション

プレゼンテーション層のコントローラとフォームバリデーションを実装していきます。
コントローラの役割はリクエストされたパラメータの検証と、アプリケーション層のユースケースへの受け渡し、レスポンスの生成となります。

連載

本記事は複数記事の連載記事の1つです。

この記事に関連するコミット

コントローラの配置

プレゼンテーション層に配置するコントローラですが、Laravel標準の「app\Http\Controllers」に配置します。
コントローラの位置を変えることは出来ますが、この辺りはフレームワークのLaravelに強く依存するのでそのままにします。

OrderControllerを作成して、findcreateメソッドを追加します。

find

注文IDを指定すると対象の注文データを返却するエンドポイントです。

create

新しい注文データを新規作成するエンドポイントです。

バリデーション

LaravelのFormRequestを使用してパラメータが妥当であるかチェックします。
FormRequestは強力で、値の型(文字列。数値)や以上・以下からデータベース上の存在確認までチェック出来ますが、どこまでチェックするべきか注意が必要です。

FormRequestでチェックすべきルールと、ドメインでチェックすべきルールを区別します。
ここはプレゼンテーション層なので、プレゼンテーション層として知っていて良い知識のみをチェックします。
具体的には、値の必須、型などが挙げられます。

ドメインでは値の以上・以下やテーブル上の存在判定など、ドメインとして持つべき知識はドメイン側でチェックします。

事例

例えば、ECサイトの注文による新規登録フォームを追加します。
あとから電話注文も対応することになったので電話注文用の登録フォームも追加します。
すると、ECサイト注文と電話注文は同じ注文を作るため、FormRequestのバリデーションルールは似通った物になります。
さらに、外部システムから注文を取り込む機能が必要になれば、どんどん増えていきます。
これらは別々の画面からのリクエストなので、FormRequestファイルは別々のものになります。

ドメインで保証すべきルールがプレゼンテーション層に漏れてしまうと、変更時の漏れなどに繋がり保守が難しくなります。

JSONレスポンス

今回はAPIとして実行するバックエンドにするので、レスポンスはJSONで返却します。

return response()->json([
    'id' => $order->id,
    'orderNumber' => $order->orderNumber,
    'orderDatetime' => $order->orderDatetime,
]);

JSONに変換する

コントローラー内で直接JSONを定義しています。
複雑なオブジェクトを返すエンドポイントになると別ファイルに定義したほうが良いでしょう。

どのような形で返却する必要があるのか知っているべきなのはプレゼンテーション層なので「app\Http\Response」等に作成します。

ミスしやすいパターンとして、よし!単純にOrderを取得するエンドポイントだからドメインのエンティティ(Order.php)にtoJsonメソッドを作って、そのまま返却しよう!

と、ドメイン層に定義するケースがありますが、これは辞めたほうがいいでしょう。

ドメイン層に定義した「toJson」はあくまでエンティティをJSONに変換する責務を担っているだけです。
決して、APIエンドポイントのレスポンスモデルではありません。

別の用途でドメインのtoJsonを変更すると、APIのレスポンスモデルまで変わってしまいます。
レスポンスモデルはドメインに依存せず、プレゼンテーション層で別途定義しましょう。

ルーティング

api.phpにルーティングを記載します。

Route::prefix('orders')->group(function (): void {
    Route::get('/{orderId}', [OrderController::class, 'find']);
    Route::post('/', [OrderController::class, 'create']);
});

プログラミングカテゴリの最新記事