こんにちは、ソーイ株式会社の髙﨑です。
Laravelでの開発に慣れてくると、
- Controllerが肥大化する
- 命名が統一されない
- 同じ処理を何度も書いてしまう
といった問題にぶつかることが増えてきました。
今回は、GitHubで公開されている「Laravel Best Practices」(Laravelでよく採用される設計・実装方針をまとめたコミュニティベースのガイド)を実務で活用してみて、特に効果があった内容をまとめます。
TL;DR
- 命名規則を揃えるだけでもレビュー効率がかなり変わった
- Controllerから処理を分離すると修正時の影響範囲を追いやすくなった
- 共通化は有効だが、やりすぎると逆に読みにくくなる
- 「とりあえず動かす」実装を続けると後からかなり辛くなる
目次
- はじめに
- Laravel Best Practicesを読んだきっかけ
- 実務で特に意識したこと
3-1. 命名規則を統一する重要性
3-2. 単一責任を意識した責務分離
3-3. 同じ処理を繰り返し書かない - 実際に活用して感じた変化
はじめに
日頃の業務では、Laravelを使ったAPI開発を行う機会が多いのですがスピード重視でコーディングをしていると、Controllerに処理をまとめて書くことも多く、実装を優先して進めていました。
実際、仕様変更のたびに関連処理を探し回ることが増え、修正に時間がかかっていました。
そこで参考にしたのが、GitHubで公開されている「Laravel Best Practices」です。
これはLaravel公式ドキュメントではなく、Laravelコミュニティでよく使われる設計・実装方針をまとめたガイドです。
内容としては、
- Fat Controllerを避ける
- 重複コードを減らす
- 命名規則を統一する
- ビジネスロジックを分離する
といった、保守性を意識した考え方が中心でした。
今回は、その中でも実務で特に効果があった内容を書いていきます。
Laravel Best Practicesを読んだきっかけ
これまでLaravelでの開発を行う中で、「とりあえず動くものを作る」ことを優先して実装してしまう場面がありました。
すると、
- Controllerに処理が集中する
- 命名が統一されていない
- 同じような処理を複数箇所で実装している
といった状態になり、後からコードを読み返した際に、修正しづらさや保守の難しさを感じることがありました。
また、コードレビューでも責務分離や命名について指摘をいただくことがあり、「読みやすく保守しやすいコードを書くにはどうすればよいのか」を改めて考えるようになりました。
そんな中で、Laravel Best Practices の記事を読み、実務でも少しずつ活用して実装してみることにしました。
今回は、その中でも実務で活用して、特に改善を実感できたものについてまとめています。
実務で意識したこと
命名規則を統一する
例えばユーザーの取得処理だけでも、人によって下記のように命名がバラバラになるかと思います。
getUserfetchUserfindUser
レビュー時にも、「このメソッドは何が違うのか?」を毎回確認する必要があり、読み手側のコストが高い状態でした。
私自身コーディングしていて、「ユーザーの取得処理を修正したいのに、どのメソッドに該当の処理が記載されているのかわからない」といった苦労をすることがありましたが、命名規則を統一することで修正すべきコードがどこにあるのかスムーズに見つけられるようになりました。
単一責任を意識した責務分離
以前はController内に、
- バリデーション
- データ更新処理
- メール送信
- レスポンス生成
などをまとめて実装してしまうことがあり、その結果、1つのメソッドに処理が集まり、修正時はControllerを上から順に追わないと影響範囲が分からない状態でした。
Before
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required',
'email' => 'required|email',
]);
$user = User::create($validated);
Mail::to($user->email)
->send(new UserRegisteredMail($user));
return response()->json([
'message' => 'User created',
'user' => $user
]);
}
そこで、ビジネスロジックをServiceクラスへ切り出したり、バリデーションをRequestへ分離したりすることで、それぞれの責務を明確にしました。
実務では外部サービスとの連携処理を専用のServiceへ分離したことで、追加実装の際もController側の修正を最小限に抑えながら対応できました。
After
// Controller
class UserController extends Controller
{
public function __construct(
private UserService $userService
) {}
public function store(StoreUserRequest $request)
{
$user = $this->userService->create(
$request->validated()
);
return response()->json([
'message' => 'User created',
'user' => $user
]);
}
}
// Service
class UserService
{
public function create(array $data): User
{
$user = User::create($data);
Mail::to($user->email)
->send(new UserRegisteredMail($user));
return $user;
}
}
一方で、細かく分割しすぎると逆に処理の流れを追いづらくなる場面もあります。
業務でも不用意に分割を行ったことで、不具合の原因がどこにあるのか見つけ出すのに苦労したこともありました。
同じ処理を繰り返し書かない
実装を進める中で、同じバリデーション処理やデータ整形、レスポンス生成を複数箇所に書いてしまうことがありました。
最初は実装速度を優先していましたが、後から仕様変更が入った際に、修正箇所が複数に散らばってしまい、修正漏れが発生していました。
Before
public function store(Request $request)
{
$data = [
'name' => trim($request->name),
'email' => strtolower($request->email),
];
User::create($data);
}
public function update(Request $request, User $user)
{
$data = [
'name' => trim($request->name),
'email' => strtolower($request->email),
];
$user->update($data);
}
そこで、共通化できる処理については、Serviceクラスや共通メソッドへ切り出すように意識しました。
これにより、修正箇所を追いやすくなり、保守面ではかなり楽になったと感じています。
After
private function formatUserData(Request $request): array
{
return [
'name' => trim($request->name),
'email' => strtolower($request->email),
];
}
public function store(Request $request)
{
User::create(
$this->formatUserData($request)
);
}
public function update(Request $request, User $user)
{
$user->update(
$this->formatUserData($request)
);
}
ただし、共通化についても、逆に処理が複数ファイルに散らばってしまい、意図が分かりづらくなることもあるため、「本当に共通化するべきか」は検討して進めることが大切です。
実際に活用して感じた変化
Laravel Best Practices の内容を実務で活用するようになってから、特に感じたのは、「コードを書く時の視点」が以前と変わったことです。
命名規則や責務分離、共通化について学んでからは、「将来的な改修に対応できる柔軟な実装になっているか」「自分以外が見て読みやすいコードになっているか」を意識してコードを書くことが増えました。
一方で、Best Practice を強く意識しすぎることで、必要以上にクラスを分割してしまったり、共通化を優先しすぎて逆に分かりづらくなってしまう危険性もあります。
今回、Laravel Best Practices を読むことで、単にLaravelの書き方を学ぶだけではなく、「ただ動く実装」から「将来を考えた実装」を行うことができるように成長できたと感じています。
今回の記事が、Laravelでの設計やコードの書き方を考える際の参考になれば幸いです。
参考
お知らせ
技術ブログを週1〜2本更新中、ソーイをフォローして最新記事をチェック!
https://qiita.com/organizations/sewii


