Laravelアプリにリポジトリパターンを適用する

ta9to
ta9to
Mar 4, 2019 · 5 min read

目的と背景

主に学習目的でwebアプリをAWSやGCPなどで運用しているのですが、なるべく低コストで運用しようとして各サービスの無料枠で色々頑張っているとデータのIO先をころころ変えたくなります

でちょうど良くLaravelのEloquentで簡単に実装したCRUDがあったので、これにリポジトリパターンを適用してアプリケーションで利用するデータのストレージエンジンの交換を容易にできる状態を実装してみました。

現状

  • 外部のAPIから取得したデータをMySQLにバッチで保存している
  • MySQLに保存されたデータをEloquentを利用して取得している

課題

  • GCPのCloudSQL(MySQL)が意外と高い(約5000円/月)

やりたいこと

  • CloudSQLをいったん停止したい
  • ViewがEloquent依存しちゃってるけどAPI叩いてもらったレスポンスでEloquentインスタンス生成すればアプリの実装をほとんど変えずにいける
  • でもパフォーマンス的に都合が悪かったりしたらまたMySQLに戻りたい

→ リポジトリパターンで交換しやすいようにした上でMySQL使わない実装に取り替えよう

実装before / after
before

↑ Eloquentのall、findメソッドを利用してコントローラでデータ取得を行なっています。今回の要件は

  • 元々のデータソースは外部のAPIからJSONで取得できるものである
  • Eloquentと、EloquentのCollectionをそれぞれ返してViewで使っているのでそれはそのまま使いたい(ViewのEloquent依存は一旦許容する)
  • 都合が悪かったらすぐ元に戻したい

なので以下の仕様を満たす実装をします。

  • Controllerからは直接データストレージを操作せずRepositoryを介する
  • 実装の交換はServiceProviderでInterfaceのbind先を変更するのみで対応できるようにする

after(実装サンプル)

↑ Repositoryにデータの取得処理を隠蔽した状態です。こうすることでEloquentとControllerを疎にしてRepositoryがどんな方法でデータを取得するのかControllerは気にしなくて良くなります。実際のRepository実装ではなくInterfaceを注入していますが、このInterfaceにどの実装を注入するかを後述のServiceProviderで解決することで実装の取り替えを容易にするという目的を達成します。

↑ Repositoryの中身です。これはEloquentでデータソースを取得するパターンのものです。

↑ Interfaceです。

↑ ServiceProviderでInterfaceとRepositoryをbindします。実装を取り替えたい場合はここでクラスを切り替えるだけで対応できます。今回は1つのInterfaceにつき常に1つのRepository実装がbindされていますが、同じInterfaceでも特定のクラスにおいては異なるクラスを注入したいという場合には以下のように制御できます。

$this->app->when(PhotoController::class)
->needs(Filesystem::class)
->give(function () {
return Storage::disk('local');
});
$this->app->when([VideoController::class, UploadController::class])
->needs(Filesystem::class)
->give(function () {
return Storage::disk('s3');
});

↑ CloudSQLをいったん落とすために取り替えたAPIからデータを取得してEloquentを生成して返す実装です。めちゃめちゃ適当ですが急ぎだったので雑なまま終わらせました。

まとめ

今回はインフラコスト都合でIO先を切り替えやすくしたいというのがあったのでRepositoryパターンをLaravelっぽく適用して対応しました。

次回はValueObjectやDomainModelなどDDD的な文脈でのPOPOを活用して複雑なビジネスロジックを複数含むアプリケーションをいかにシンプルに維持して制御するかというところを紹介したいと思います。

Nyle Engineering Blog

ナイル株式会社のエンジニアブログです。ナイル社内で利用している技術の情報や、社内の様子などを発信しています。

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store