1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Day14 — コントローラを薄く保つ設計:リクエストからビジネスロジックを分離する

1
Last updated at Posted at 2025-12-13

はじめに

Day13 では、

✅ ミドルウェアで「入口」を整える
✅ 認証・ログ・共通処理を集約する

ところまで進みました。

今日はその次の段階です。

じゃあコントローラには何を書くべきなのか?

ここを間違えると、
Fat Controller(コントローラに記載が過多となる)問題 に突入します。

今日のゴール

・コントローラの「正しい役割」を説明できる

・Fat Controller がなぜダメか理解できる

・Service クラスを使って責務を分離できる

・「読める・保守できる API コード」を書ける

まず見てほしい「ダメなコントローラ」

public function store(Request $request)
{
    // バリデーション
    if (!$request->title) {
        return response()->json(...);
    }

    // DB保存
    $post = new Post();
    $post->title = $request->title;
    $post->save();

    // 通知送信
    Mail::to(...)->send(...);

    // レスポンス
    return response()->json(...);
}

一見動きますが、問題点は…

・処理が多すぎる

・テストしづらい

・仕様変更に弱い

・再利用できない

これが Fat Controller です。

適切な考え方:コントローラは「交通整理」

コントローラの役割はこれだけ。

「リクエストを受け取り、適切な処理に流し、レスポンスを返す」

つまり、

・ロジックは書かない

・判断は最小限

・処理は他に委譲

責務分離の基本構成

Request
  ↓
Controller(薄い)
  ↓
Service(ビジネスロジック)
  ↓
Model(DB操作)

実践:Service クラスを作る

① Service クラス作成

app/Services/PostService.php

<?php

namespace App\Services;

use App\Models\Post;

class PostService
{
    public function create(array $data)
    {
        return Post::create([
            'title' => $data['title'],
        ]);
    }
}

② Controller から Service を呼ぶ

use App\Services\PostService;

class PostController extends Controller
{
    public function store(Request $request, PostService $postService)
    {
        $post = $postService->create($request->only('title'));

        return response()->json([
            'status' => 'success',
            'data' => $post
        ], 201);
    }
}

何が良くなったのか?

Before After
ロジックが詰まっている 処理が1行
読みにくい 一目で分かる
テスト困難 Service単体テスト可能
再利用不可 他APIから再利用可能

よくある疑問:どこまで分けるべき?

✔ 分けるべきもの

・ビジネスルール

・複数モデルをまたぐ処理

・将来変更されそうな処理

❌ 分けなくていいもの

・単純な1行取得

・その場限りの処理

「迷ったら分ける」くらいでOK です。

リクエストのバリデーションはどこに書く?

バリデーションは FormRequest に切り出します。

php artisan make:request StorePostRequest
public function rules()
{
    return [
        'title' => 'required|string|max:255'
    ];
}

Controller はさらに薄くなります。

public function store(StorePostRequest $request, PostService $postService)
{
    $post = $postService->create($request->validated());

    return response()->json([
        'status' => 'success',
        'data' => $post
    ], 201);
}

これが「綺麗な API コントローラ」

・ロジックが無い

・処理が流れるだけ

・役割が明確

・読んで安心できる

今日のまとめ

・コントローラは「交通整理役」

・Fat Controller は避ける

・ロジックは Service クラスへ

・バリデーションは FormRequest へ

・責務分離で保守性・可読性が爆上がり

次回 Day15

次はいよいよ 認証の核心 に入ります。

Day15 — JWTとは?仕組みを図解しながらLaravelで発行してみる

ここから
「本物の Web API」
になっていきます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?