Day 3・ルーティングとコントローラー、ルートモデルバインディング
コントローラの責務と、薄く保つ考え方
コントローラは「受け取って・振り分けて・返す」係。ビジネスロジックを溜め込まない設計を理解する。
コントローラの役割
コントローラは、ルーティングが決めた行き先です。役割はシンプルで、「リクエストを受け取り」「必要な処理を適切な担当に振り分け」「結果を画面やJSONとして返す」という交通整理です。自分自身が計算や複雑な判断を全部抱え込む場所ではありません。
なぜコントローラは薄くあるべきか(単一責任)
1つのクラスに「入力の受け取り」「業務ルールの計算」「DB操作」「表示の組み立て」を全部詰め込むと、修正のたびに巨大なメソッドを読み解く必要が出て、テストも難しくなります。これが というアンチパターンです。責務を1つに絞る(単一責任の原則)ことで、変更の影響範囲が小さくなり、読みやすく・テストしやすくなります。
リソースコントローラ
Day3のレッスン1で見たリソースルートに対応するのが「リソースコントローラ」です。index・create・store・show・edit・update・destroy という定番メソッドを持つコントローラを、コマンド1つで雛形生成できます。命名が揃うので、どのメソッドが何をするか誰でも予測できます。
// $ 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 太ったコントローラ
同じ「投稿を保存する」処理でも、書き方で保守性が大きく変わります。業務ロジックをコントローラに直書きしたものと、処理を別の担当(サービス層など)に委ねたものを比べてみましょう。
太ったコントローラ(アンチパターン)
業務ルールや外部連携までコントローラのメソッドに詰め込むと、肥大化してテストできない。
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');
}薄いコントローラ(推奨)
コントローラは受け取って委ねて返すだけ。業務ロジックはサービス層に置く。
public function store(StorePostRequest $request, PostService $service)
{
// 入力チェックはフォームリクエストへ、業務ロジックはサービス層へ委譲
$post = $service->create($request->validated());
return redirect()->route('posts.show', $post);
}補足
上の良い例では、業務ロジックを に、入力チェックをフォームリクエストに切り出しています。コントローラは「入力を受け取り、担当に委ね、結果を返す」だけの薄い層になっています。なお、引数に書いた PostService は、自分で new しなくてもLaravelのコンテナ(依存解決の仕組み)が自動で用意して渡してくれます。生成コストが高いものや状態を共有したいものは、コンテナに (シングルトン)として登録し、アプリ内で常に同一インスタンスを使い回すこともできます。
コントローラを薄く保つ指針
- 1メソッドは「受け取る・委ねる・返す」の3ステップに収まるのが理想。
- 入力の検証は、コントローラではなくフォームリクエストに寄せる。
- 業務ルール(いつ・どんな計算をするか)は、サービス層やモデルに置く。
- 同じ処理を複数のコントローラから呼びたくなったら、それは切り出すサイン。
- テストしづらいと感じたら、責務が混ざっている可能性を疑う。
面接ではこう言う
「コントローラは受け取って委ねて返すだけの薄い層に保ちます。業務ロジックまで書き込むと になり、テストも保守も難しくなります。私は入力検証をフォームリクエストへ、業務ロジックを へ切り出し、単一責任を意識してコントローラを薄く保っています」と言えると、設計を理解していると伝わります。
読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。
理解度チェック
答えられれば、面接で説明できる状態に一歩近づきます。
コントローラを「薄く保つ」とは、どういう状態を目指すことか。
コントローラに業務ロジックを書きすぎると、どんな問題が起きるか。「fat controller」という言葉を使って説明せよ。
記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。