LLaravel Bootcamp

Day 3ルーティングとコントローラー、ルートモデルバインディング

コントローラの責務と、薄く保つ考え方

コントローラは「受け取って・振り分けて・返す」係。ビジネスロジックを溜め込まない設計を理解する。

コントローラの役割

コントローラは、ルーティングが決めた行き先です。役割はシンプルで、「リクエストを受け取り」「必要な処理を適切な担当に振り分け」「結果を画面やJSONとして返す」という交通整理です。自分自身が計算や複雑な判断を全部抱え込む場所ではありません。

なぜコントローラは薄くあるべきか(単一責任)

1つのクラスに「入力の受け取り」「業務ルールの計算」「DB操作」「表示の組み立て」を全部詰め込むと、修正のたびに巨大なメソッドを読み解く必要が出て、テストも難しくなります。これが というアンチパターンです。責務を1つに絞る(単一責任の原則)ことで、変更の影響範囲が小さくなり、読みやすく・テストしやすくなります。

リソースコントローラ

Day3のレッスン1で見たリソースルートに対応するのが「リソースコントローラ」です。index・create・store・show・edit・update・destroy という定番メソッドを持つコントローラを、コマンド1つで雛形生成できます。命名が揃うので、どのメソッドが何をするか誰でも予測できます。

PHP
// $ php artisan make:controller PostController --resource

class PostController extends Controller
{
    public function index() { /* 一覧を返す */ }
    public function create() { /* 作成フォームを返す */ }
    public function store(Request $request) { /* 保存する */ }
    public function show(Post $post) { /* 詳細を返す */ }
    public function edit(Post $post) { /* 編集フォームを返す */ }
    public function update(Request $request, Post $post) { /* 更新する */ }
    public function destroy(Post $post) { /* 削除する */ }
}
リソースコントローラの雛形(定番メソッドが揃う)

薄いコントローラ vs 太ったコントローラ

同じ「投稿を保存する」処理でも、書き方で保守性が大きく変わります。業務ロジックをコントローラに直書きしたものと、処理を別の担当(サービス層など)に委ねたものを比べてみましょう。

太ったコントローラ(アンチパターン)

業務ルールや外部連携までコントローラのメソッドに詰め込むと、肥大化してテストできない。

PHP
public function store(Request $request)
{
    // バリデーションも、業務ルールも、DB保存も、通知も全部ここに…
    $data = $request->all();
    if (mb_strlen($data['title']) > 100) { /* 独自チェック */ }
    $slug = mb_strtolower(str_replace(' ', '-', $data['title']));
    $post = new Post();
    $post->title = $data['title'];
    $post->slug = $slug;
    $post->save();
    // メール送信やSlack通知までここに直書き…
    Mail::to($post->user)->send(new PostCreated($post));
    return redirect('/posts');
}

薄いコントローラ(推奨)

コントローラは受け取って委ねて返すだけ。業務ロジックはサービス層に置く。

PHP
public function store(StorePostRequest $request, PostService $service)
{
    // 入力チェックはフォームリクエストへ、業務ロジックはサービス層へ委譲
    $post = $service->create($request->validated());

    return redirect()->route('posts.show', $post);
}

補足

上の良い例では、業務ロジックを に、入力チェックをフォームリクエストに切り出しています。コントローラは「入力を受け取り、担当に委ね、結果を返す」だけの薄い層になっています。なお、引数に書いた PostService は、自分で new しなくてもLaravelのコンテナ(依存解決の仕組み)が自動で用意して渡してくれます。生成コストが高いものや状態を共有したいものは、コンテナに (シングルトン)として登録し、アプリ内で常に同一インスタンスを使い回すこともできます。

コントローラを薄く保つ指針

  • 1メソッドは「受け取る・委ねる・返す」の3ステップに収まるのが理想。
  • 入力の検証は、コントローラではなくフォームリクエストに寄せる。
  • 業務ルール(いつ・どんな計算をするか)は、サービス層やモデルに置く。
  • 同じ処理を複数のコントローラから呼びたくなったら、それは切り出すサイン。
  • テストしづらいと感じたら、責務が混ざっている可能性を疑う。

面接ではこう言う

「コントローラは受け取って委ねて返すだけの薄い層に保ちます。業務ロジックまで書き込むと になり、テストも保守も難しくなります。私は入力検証をフォームリクエストへ、業務ロジックを へ切り出し、単一責任を意識してコントローラを薄く保っています」と言えると、設計を理解していると伝わります。

読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。

理解度チェック

答えられれば、面接で説明できる状態に一歩近づきます。

Q1

コントローラを「薄く保つ」とは、どういう状態を目指すことか。

Q2

コントローラに業務ロジックを書きすぎると、どんな問題が起きるか。「fat controller」という言葉を使って説明せよ。

記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。