Laravelでアプリを開発していくと、コントローラーやモデルが肥大化し、ロジックの分離や依存の抽象化が課題になります。
そこで登場するのがサービス層とリポジトリパターン疎結合・テスト可能な設計を実現します。
本記事では、Laravelでサービス層とリポジトリパターンを導入する方法を、実用コード付きでわかりやすく解説します。

目次
なぜサービス層とリポジトリが必要か?
LaravelのControllerは便利ですが、以下のような課題に直面します:
- データ取得やビジネス処理が混在して読みづらい
- ロジックが重複して再利用しづらい
- テストしにくくなる
このような問題を解決するために、役割ごとに責務を分離するのが「サービス層+リポジトリパターン」です。
構成イメージ
/app
├── Http │ └── Controllers │ └── TaskController.php ├── Services │ └── TaskService.php ├── Repositories │ ├── TaskRepositoryInterface.php │ └── TaskRepository.php
ステップ1:リポジトリインターフェースの定義
// app/Repositories/TaskRepositoryInterface.php
<?php
namespace App\Repositories;
interface TaskRepositoryInterface {
public function all();
public function find($id);
public function create(array $data);
public function delete($id);
}
ステップ2:リポジトリの実装
// app/Repositories/TaskRepository.php
<?php
namespace App\Repositories;
use App\Models\Task;
class TaskRepository implements TaskRepositoryInterface {
public function all() {
return Task::all();
}
public function find($id) {
return Task::find($id);
}
public function create(array $data) {
return Task::create($data);
}
public function delete($id) {
return Task::destroy($id);
}
}
ステップ3:サービス層の作成
// app/Services/TaskService.php
<?php
namespace App\Services;
use App\Repositories\TaskRepositoryInterface;
class TaskService {
protected $taskRepo;
public function __construct(TaskRepositoryInterface $taskRepo) {
$this->taskRepo = $taskRepo;
}
public function getAllTasks() {
return $this->taskRepo->all();
}
public function createTask(array $data) {
return $this->taskRepo->create($data);
}
}
ステップ4:サービスとリポジトリのバインド
AppServiceProvider
で依存注入を設定します。
// app/Providers/AppServiceProvider.php
use App\Repositories\TaskRepository;
use App\Repositories\TaskRepositoryInterface;
public function register() {
$this->app->bind(TaskRepositoryInterface::class, TaskRepository::class);
}
ステップ5:コントローラーでサービスを利用
// app/Http/Controllers/TaskController.php
<?php
namespace App\Http\Controllers;
use App\Services\TaskService;
use Illuminate\Http\Request;
class TaskController extends Controller {
protected $taskService;
public function __construct(TaskService $taskService) {
$this->taskService = $taskService;
}
public function index() {
$tasks = $this->taskService->getAllTasks();
return view('tasks.index', compact('tasks'));
}
public function store(Request $request) {
$this->taskService->createTask($request->only('title'));
return redirect()->route('tasks.index');
}
}
まとめ:サービス層+リポジトリで得られる効果
- 関心の分離(Controller, Service, Repositoryで役割明確)
- テスト容易性の向上(モック注入が簡単に)
- 拡張性・保守性の向上(DB変更やロジック変更に柔軟対応)
Laravelでの開発を「MVC以上の設計」に進化させるなら、サービス層とリポジトリパターンは避けて通れない技術です。
次は「DIコンテナの理解」「ユースケース層の導入」や「ドメイン駆動設計(DDD)」などに進むと、より高度なアーキテクチャが見えてきます。