チャン ゴック クオン

2015.06.02

Laravel4.2のリポジトリパターン

こんにちは。クオンです。

夏が来て、最近は暑いですね。
今回はLaravelリポジトリパターンについて書こうと思います。

Laravel4.2のドキュメントはこちらでご参考ください。

Eloquent ORM

Laravelではデータベースの接続、そしてクエリの実行に関してシンプルな解決策が提示されています。
データベース操作で、Eloquentがよく使われています。
Eloquentとは

  • Laravelに含まれるActiveRecordパターンの実装
  • たくさんの便利なメソッドが用意され、シンプルでパワフルなインターフェースを備えている

Eloquentを使用すると、データベースへのアクセスがとても簡単になります。
以下はControllerまたはServiceクラスからの、データベースアクセスの記述例になります。

このような書き方は簡単でプログラムを早く作成する事ができます。
しかし次のような問題があります。

  • データベースエンジンの変更があった場合、変更が大変
  • いつか、例えばプロジェクトが大きくなったら、MySQLではなくて、やっぱりOracleにする場合、上記の例のように、データベースアクセスを記述していたり、クラスを直接newで生成していると、変更箇所が膨大になります。

  • 単体テストがしにくい
  • Eloquentモデルをモック化できなくて、単体テストがしにくいですね。

なぜEloquentモデルをモック化できないのか?
ここでファサードについて少し話しましょう。(詳しくはこちらです)
ファサードはIoCコンテナに登録されたクラスを静的メソッド(Class:methodという形式)で呼び出すことを可能にしています。

Eventクラスが使用された場合に、エイリアスであるIlluminate\Support\Facades\Eventクラスが実際に動作しています。
ファサードはモックオブジェクトフレームワークであるMockeryと統合されていて、ファサードを簡単にモック化できます。

しかし、Eloquentはファサードを継承していないので、このように簡単にモック化できません。

上記の問題を解決するために、リポジトリパターンを使用します。

リポジトリパターン

リポジトリパターンとは

リポジトリパターンとは、データの取得、保持、元になるモデルへのマップを行うロジックを、そのデータを処理するビジネスロジックから分離します。
Laravel以外でも、リポジトリパターンは良く使われています。

Laravelリポジトリパターンの実装

まずはモデルごとに、Repositoryのインターフェースと実装クラスを作ります。
インターフェースを使用すると、コードは簡単に理解でき、メンテナンスできるようにもなります。そして、実装クラスを差し替えることができます。

以下はサンプルとして、UserモデルのUser Repositoryです。

UserRepositoryInterface

EloquentでUserRepositoryInterfaceを実装します。

次はIoC(Inversion of Container)にRepositoryを登録します。

このようにContainerに登録すると、UserRepositoryInterfaceインターフェースがインジェクトされるときにUserRepositoryクラスが使用されます。

リポジトリを使用する

依存注入(DI)を使って、コントローラーまたはサービスのコンストラクタの引数にUserRepositoryInterfaceを指定します。

このようにすると、UserControllerクラス生成時にUserRepositoryインスタンスを生成し、UserControllerクラスのコンストラクタに注入されます。
次はUserRepositoryを使いましよう。

データベースリポジトリはコントローラクラスのプロパティーの一つとして、使用されます。

これでリポジトリパターンの実装は完成です。

リポジトリパターンを使用するとデータベースの変更があった場合、変更を簡単に実装できます。Repositoryクラス(例えばUserRepositoryクラス)で実装ロジックを変更すれば対応可能です。また単体テストを簡単に行う事ができます。

一方、リポジトリパターンを実装すると、プロジェクト構造が複雑になり、工数も増えますので、必要がない場合は、(例えば小さいプロジェクトなど)、リポジトリパターンを使わないほうが良いと思います。

最後まで読んでいただき、ありがとうございました。
これからも宜しくお願い致します。