【Laravel初心者向け】Controllerの肥大化を解決!?初めてService + Repository構成にしてみた感想
はじめに
なぜこの問題にぶつかったか
Laravelを触り始めた頃、私はControllerの中に Model::where() や orderBy() などを直接書いて、以下のようなコードを書いていました。
public function index()
{
$cats = Cat::whereNull('deleted_at')->orderBy('id')->get();
return $cats;
}
最初はこれで十分だと思っていましたが、処理が増えるにつれてControllerがどんどん長くなりました。他のコントローラでも似たような処理が増えてきたあたりで、「これは非効率だな」と感じました。
そこで今回は、初めて
Controller → Service → Repository → Model
という構成を実装してみたので、備忘録も兼ねて感想をまとめます。
実装してみた:Service + Repository構成
ディレクトリ構成
app/
├── Http/
│ └── Controllers/
│ └── CatController.php
├── Services/
│ └── CatService.php
├── Repositories/
│ └── CatRepository.php
├── Models/
│ └── Cat.php
コード構成
Controller(スッキリ!)
public function index()
{
$cats = $this->catService->getCatList();
return response()->json($cats);
}
Service(ビジネスロジック)
public function getCatList()
{
$cats = $this->catRepository->findAvailableCats();
return $cats->map(function ($cat) {
return [
'id' => $cat->id,
'name' => strtoupper($cat->name), // 加工ロジック
];
});
}
Repository(DB操作担当)
public function findAvailableCats()
{
return Cat::whereNull('deleted_at')->orderBy('id')->get();
}
構造イメージ
- ControllerはただServiceを呼び出す
- Serviceがビジネスロジックを管理
- Repositoryがデータ取得を担当
- ModelはEloquent ORMの役割
実行結果
実際にAPIを叩くと、整形されたデータが返ってきました:
[
{ "id": 1, "name": "三毛猫" },
{ "id": 2, "name": "黒猫" }
]
「データの整え方だけ変えたいならService」
「クエリだけ変えたいならRepository」と、メンテナンスがしやすくなりました!
実際にやって感じた3つのこと
Controllerは「やるべきことだけを呼び出す役割」になり、
ビジネスロジックはServiceへ、
DBの操作はRepositoryに…と、責任が分離されました。
• Controllerが短くなった
• ロジックの分担で混乱しにくくなった
• SQLの処理変更はRepositoryの中だけ直せばいい
結果として、Controllerの肥大化を防げて、コードの見通しも良くなりました。
ただし、「これどこに書けばいいんだろう?」と迷うこともありました。
でも慣れていくと、考えやすくなるでしょう。
まとめ
最初、「Controllerでもできるし、わざわざ構成を分ける必要ある?」と思っていました。
でも実際にやってみると、責任が分かれて処理がスムーズになるし、保守もラクになるというメリットを実感できました。
次のステップとしては:
- 複雑な検索条件をRepositoryで試す
- 複数モデルの処理をServiceでまとめる
など、さらに理解を深めたいと思います!
おわりに
この記事が、同じように「Controllerが太ってきて困ってる…」というLaravel初心者の方のヒントになれば嬉しいです!
「Repositoryって必要?」とモヤモヤしてる方にこそ、一度試してもらいたい構成です!
Discussion