Laravelでクリーンアーキテクチャを実装する方法
1. はじめに
クリーンアーキテクチャとは?
近年、ソフトウェア開発では「保守性」や「拡張性」が重要視されています。特に、大規模なプロジェクトや長期運用が求められるシステムでは、「コードがスパゲッティ化してしまい、修正が大変…」「ちょっとした変更で他の部分に影響が出てしまう…」といった課題が発生しやすくなります。
そこで登場するのが「クリーンアーキテクチャ」です。これは、ロバート・C・マーティン(通称 Uncle Bob)が提唱したソフトウェア設計の考え方で、以下のような特徴を持っています。
- ビジネスロジックを外部要因(DB・フレームワークなど)に依存させない
- 依存関係を内側 → 外側に一方向にする(依存逆転の原則)
- ドメイン(業務ルール)を第一に考える設計
Laravelの標準MVCとの違い
Laravelでは一般的に MVC(Model-View-Controller) のアーキテクチャが採用されています。
MVCはシンプルで直感的ですが、次のような問題点があります。
- ビジネスロジックがコントローラーやモデルに分散しやすい
- 変更があると、他の部分に影響を与えやすい
- データベースやフレームワークの仕様に依存しがち
クリーンアーキテクチャを取り入れることで、これらの問題を解決し、より柔軟で保守しやすい設計を実現できます。
この記事で学べること
この記事では、クリーンアーキテクチャの基本概念を説明しながら、Laravelに適用する方法を詳しく解説します。具体的には以下の内容をカバーします。
✅ クリーンアーキテクチャのレイヤー構造を理解する
✅ Laravelのフォルダ構成をクリーンアーキテクチャに最適化する
✅ 実際に「ユーザー登録」機能をクリーンアーキテクチャで実装する
この記事を読むことで、Laravelでクリーンアーキテクチャを実践できるようになり、より保守性が高く、拡張しやすいアプリケーション設計ができるようになります!💡
2. クリーンアーキテクチャの基本概念
クリーンアーキテクチャの4つのレイヤー
クリーンアーキテクチャは、コードの保守性と拡張性を高めるために、以下の4つのレイヤーに分かれています。
- エンティティ(Entities)
- アプリケーションの 最も本質的なビジネスルール を定義する。
- データベースやフレームワークに依存しない 純粋なPHPクラス で記述。
- 例:
User
エンティティ(ID、名前、メールアドレスなどを持つ)
- ユースケース(Use Cases)
- アプリケーションの ビジネスロジック(操作・処理) を実装。
- エンティティを操作し、データのやり取りを制御。
- 例:ユーザー登録やログイン処理
- インターフェース(Interface Adapters)
- ユースケースと外部のデータ(リポジトリ、API、フレームワーク)をつなぐ役割。
- コントローラー、リクエスト、レスポンス、リポジトリのインターフェースを含む。
- 例:Laravelのコントローラー、リクエストクラス
- フレームワーク・データベース(Frameworks & Drivers)
- フレームワーク(Laravel)やデータベースとの接続を担当。
- LaravelのEloquent ORMやルーティング、コントローラーなどがここに含まれる。
✅ ポイント:依存関係のルール
クリーンアーキテクチャでは、外側のレイヤーが内側のレイヤーに依存する ルールになっています。
逆に、内側のレイヤー(エンティティやユースケース)は、フレームワークやデータベースの影響を受けません。
LaravelのMVCとの違い
Laravelの一般的なMVCアーキテクチャとクリーンアーキテクチャの違いを整理すると、以下のようになります。
項目 | LaravelのMVC | クリーンアーキテクチャ |
---|---|---|
ビジネスロジックの場所 | コントローラーやモデルに分散 | ユースケースに集約 |
データベース依存 | Eloquent(ORM)に依存しがち | リポジトリパターンで切り離す |
コードのテストのしやすさ | 依存関係が強く、テストが難しい | ユースケース単位でテストしやすい |
拡張性 | 機能追加時に影響範囲が大きい | 影響範囲が限定され、保守しやすい |
例えば、LaravelのMVCでは「ユーザー登録」の処理が コントローラーやモデルに散らばりがち ですが、クリーンアーキテクチャでは ユースケース層にまとめる ことで、コードの見通しがよくなります。
まとめ
クリーンアーキテクチャは「ビジネスロジックを独立させる」ことが最大の特徴です。
これにより、フレームワークに依存せず、長期的に保守しやすい設計 を実現できます。
3. Laravelでのフォルダ構成
クリーンアーキテクチャをLaravelに適用するためには、フォルダ構成 を適切に設計することが重要です。
ここでは、標準のLaravelの構成と、クリーンアーキテクチャを適用した構成を比較しながら解説します。
Laravelの標準フォルダ構成(MVC)
まず、Laravelの標準的なMVC構成は以下のようになっています。
app/
├── Http/
│ ├── Controllers/ ← コントローラー
│ ├── Requests/ ← バリデーション用リクエスト
│ └── Middleware/ ← ミドルウェア
├── Models/ ← Eloquentモデル
├── Providers/ ← サービスプロバイダ
database/
├── migrations/ ← マイグレーション
├── seeders/ ← データのシーダー
routes/
├── web.php ← ルーティング定義
この構成では、ビジネスロジックがコントローラーやモデルに分散しがち で、プロジェクトが大きくなると保守が難しくなります。
クリーンアーキテクチャ適用後のフォルダ構成
クリーンアーキテクチャを適用すると、フォルダ構成は以下のようになります。
app/
├── Domain/ # エンティティ、リポジトリインターフェース
│ ├── Entities/
│ ├── Repositories/
├── UseCase/ # ビジネスロジック(ユースケース)
│ ├── User/
│ │ ├── RegisterUserUseCase.php
│ │ ├── UpdateUserUseCase.php
├── Infrastructure/ # データベースなどの実装
│ ├── Repositories/
│ │ ├── UserRepository.php
│ ├── Persistence/ # データベースとのやりとり
│ ├── API/ # 外部APIとの接続
├── Interface/ # コントローラー、リクエスト、レスポンス
│ ├── Controllers/
│ ├── Requests/
│ ├── Presenters/ # データの整形(レスポンス)
各フォルダの役割
フォルダ名 | 役割 |
---|---|
Domain/ | アプリのビジネスルール(エンティティ、リポジトリインターフェース) |
UseCase/ | アプリケーションのユースケース(ユーザー登録、更新などの処理) |
Infrastructure/ | データベースや外部APIとの接続(リポジトリ実装) |
Interface/ | コントローラー、リクエスト、レスポンス(外部との接続) |
Laravel標準構成との違い
- ビジネスロジックがユースケース層に集約(コントローラーがシンプルになる)
- データベースの実装がリポジトリ層に分離(Eloquentに依存しない設計が可能)
- リクエストとレスポンスの整形をPresenterで統一(データの一貫性が保てる)
まとめ
このフォルダ構成を採用することで、Laravelのフレームワークに依存しない設計になり、テストしやすく、拡張性の高いアプリケーション を構築できます。
4. 実装例:シンプルな「ユーザー登録」機能を作る
ここからは、Laravelでクリーンアーキテクチャを適用しながら、「ユーザー登録」機能を実装していきます。
クリーンアーキテクチャのレイヤーごとにコードを分け、保守性の高い設計 にするのがポイントです!
4.1 エンティティ(Domain)
まずは、ユーザーのエンティティを定義します。
エンティティは、アプリケーションの本質的なデータ構造とルール を表します。
📂 app/Domain/Entities/User.php
namespace App\Domain\Entities;
class User
{
private string $name;
private string $email;
private string $password;
public function __construct(string $name, string $email, string $password)
{
$this->name = $name;
$this->email = $email;
$this->password = $password;
}
public function getName(): string
{
return $this->name;
}
public function getEmail(): string
{
return $this->email;
}
public function getPassword(): string
{
return $this->password;
}
}
✅ ポイント
User
エンティティは、データの持ち方を定義するだけ で、Eloquent(ORM)には依存しません。- Laravelの
User
モデルとは別に、ドメインのエンティティ を用意します。
4.2 リポジトリインターフェース(Domain)
次に、ユーザーのデータを保存・取得するためのインターフェース を定義します。
データの取得方法はここでは決めず、後でリポジトリクラス(実装)を作成します。
📂 app/Domain/Repositories/UserRepositoryInterface.php
namespace App\Domain\Repositories;
use App\Domain\Entities\User;
interface UserRepositoryInterface
{
public function save(User $user): void;
}
✅ ポイント
- EloquentやDBに依存しない設計 にするため、インターフェースを作成。
- ユースケース層は、この
UserRepositoryInterface
を通じてデータを操作します。
4.3 ユースケース(UseCase)
次に、ユーザー登録のビジネスロジック をユースケース層に実装します。
📂 app/UseCase/User/RegisterUserUseCase.php
namespace App\UseCase\User;
use App\Domain\Entities\User;
use App\Domain\Repositories\UserRepositoryInterface;
class RegisterUserUseCase
{
private UserRepositoryInterface $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
public function execute(string $name, string $email, string $password): void
{
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$user = new User($name, $email, $hashedPassword);
$this->userRepository->save($user);
}
}
✅ ポイント
- ユーザーのパスワードをハッシュ化し、エンティティを作成。
UserRepositoryInterface
を経由してデータを保存。(Eloquentは未使用)- フレームワークに依存しない設計 なので、どんな環境でも動作可能!
4.4 リポジトリの実装(Infrastructure)
次に、データベースと接続するリポジトリの実装 を行います。
ここで初めて Eloquent を使用 します。
📂 app/Infrastructure/Repositories/UserRepository.php
namespace App\Infrastructure\Repositories;
use App\Domain\Entities\User as DomainUser;
use App\Domain\Repositories\UserRepositoryInterface;
use App\Models\User as EloquentUser;
class UserRepository implements UserRepositoryInterface
{
public function save(DomainUser $user): void
{
EloquentUser::create([
'name' => $user->getName(),
'email' => $user->getEmail(),
'password' => $user->getPassword(),
]);
}
}
✅ ポイント
- クリーンアーキテクチャでは、リポジトリがEloquentをカプセル化 する。
- ユースケース層はEloquentの存在を知らない ので、Laravel以外のDBにも対応可能。
4.5 コントローラー(Interface)
次に、ユーザー登録リクエストを受け取るコントローラー を実装します。
📂 app/Interface/Controllers/UserController.php
namespace App\Interface\Controllers;
use App\UseCase\User\RegisterUserUseCase;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class UserController
{
private RegisterUserUseCase $registerUserUseCase;
public function __construct(RegisterUserUseCase $registerUserUseCase)
{
$this->registerUserUseCase = $registerUserUseCase;
}
public function register(Request $request): JsonResponse
{
$this->registerUserUseCase->execute(
$request->input('name'),
$request->input('email'),
$request->input('password')
);
return response()->json(['message' => 'User registered successfully']);
}
}
✅ ポイント
- コントローラーはユースケースを呼び出すだけ で、ビジネスロジックは書かない。
- ユースケースを使うことで、リクエストの流れが明確になる。
4.6 ルーティングと動作確認
📂 routes/web.php
にルートを追加します。
use App\Interface\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::post('/register', [UserController::class, 'register']);
📌 動作確認(APIリクエスト)
curl -X POST http://localhost/register \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com", "password": "secret"}'
✅ これで、クリーンアーキテクチャで実装したユーザー登録機能が動作 する! 🎉
まとめ
- クリーンアーキテクチャを適用すると、ビジネスロジックが明確に分離 され、保守性が向上。
UserRepositoryInterface
を使うことで、Eloquentに依存しない設計 が可能。- ユースケース層がデータフローを統制 し、拡張性の高いアプリケーションが作れる!
5. まとめ
この記事では、Laravelにクリーンアーキテクチャを適用する方法を学びました。
ここで、重要なポイントを振り返ります。
✅ クリーンアーキテクチャのメリット
- ビジネスロジックを分離できる
- コントローラーやモデルにロジックを詰め込まないため、コードの見通しが良くなる。
- フレームワークやデータベースに依存しない設計ができる
- ユースケース層が独立しているため、Laravel以外のフレームワークにも移行しやすい。
- テストがしやすい
- ユースケースを単体テストできるので、データベースを使わなくてもロジックの検証が可能。
- 機能追加や変更に強い
- 影響範囲が明確なので、新機能を追加しやすく、既存コードへの影響を最小限に抑えられる。
✅ LaravelのMVCとの違い
項目 | LaravelのMVC | クリーンアーキテクチャ |
---|---|---|
ビジネスロジックの場所 | コントローラーやモデルに分散 | ユースケース層に集約 |
データの管理方法 | Eloquentモデルに依存 | リポジトリパターンを使用 |
コードのテストのしやすさ | Eloquentが絡むとテストが難しい | ユースケース単位でテスト可能 |
保守性 | コードが肥大化しやすい | 各層が明確に分離されている |
✅ 今後の応用
今回の「ユーザー登録機能」の実装をベースに、以下のような機能もクリーンアーキテクチャで実装できます。
- ログイン機能(認証処理をユースケース層で管理)
- パスワードリセット機能(ユースケース層でメール送信を制御)
- ユーザー情報の更新・削除(リポジトリを使ったデータ管理)
- 外部APIとの連携(Infrastructure層でAPIをラップする)
クリーンアーキテクチャを採用することで、大規模なアプリケーションでもスケールしやすく、保守性の高いコードを書くことができる ようになります!💡
📌 最後に
Laravelでクリーンアーキテクチャを適用するのは最初は難しく感じるかもしれませんが、実際にプロジェクトで取り入れることで、その効果を実感できるはずです。
ぜひ、実際のアプリ開発で試してみてください!🚀