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

アプリケーション

DB操作に関連するスマートな実装パターンであるリポジトリパターンについてかいてみようかと思います。

リポジトリパターンとは

データの操作に関連するロジックをビジネスロジックから切り離し、抽象化したレイヤに任せることで保守や拡張性を高めるパターンです。
(必ずしもDB操作のロジックのみを留めるパターンというわけではないそうです。)

Laravelにリポジトリパターンを取り入れることで、

  • テストがしやすくなる
  • DBエンジンの変更に対応しやすくなる
  • データ操作のロジックが1箇所にまとまり、管理しやすくなる

といったメリットを得ることができます。

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

Modelと同じ単位でRepositoryディレクトリを作成します。(賛否両論あるかもです)

今回は以下のような構成でリポジトリパターンを実装していきます。

.
├── Models
│   ├── User.php
│  
├── Repositories
    └── User
        ├── UserRepository.php
        └── UserRepositoryInterface.php

インターフェース設計

まずはインターフェースを設計します。

<?php

namespace App\Repositories\User;

interface UserRepositoryInterface
{
    /**
     * Nameで1レコードを取得
     *
     * @var string $name
     * @return object
     */
    public function getFirstRecordByName($name);
}

インプリメント(実装)クラス

続いて実装クラスを用意します。
ここでは対応するモデルのDIとメソッドの実装を行います。

<?php

namespace App\Repositories\User;

use App\Models\User;

class UserRepository implements UserRepositoryInterface
{
    protected $user;

    /**
    * @param object $user
    */
    public function __construct(User $user)
    {
    $this->user = $user;
    }

    /**
     * 名前で1レコードを取得
     *
     * @var $name
     * @return object
     */
    public function getFirstRecordByName($name)
    {
        return $this->user->where('name', '=', $name)->first();
    }
}

ここから更にService層を用意してクラスを追加し、抽象度を高める場合もあるようですが、今回はこの2つのクラスのみで実装していくことにします。

Service Provider

AppServiceProvider.phpにインターフェースと実装クラスを登録します。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // User
        $this->app->bind(
            \App\Repositories\User\UserRepositoryInterface::class,
            \App\Repositories\User\UserRepository::class
        );
    }
}

Controllerで呼び出す

実装したリポジトリパターンを使用します。

<?php

namespace App\Http\Controller\User;

use App\Repositories\User\UserRepositoryInterface;

class UserController extends Controller
{
   public function __construct(UserRepositoryInterface $user_repository)
   {
      $this->user_repository = $user_repository;
   }

   public function index()
   {
      return $this->user_repository->getFirstRecordByName($name);
   }
}

インターフェースをインジェクションするだけです!

所感

モデルもコントローラーもすっきりしました。
これを機にDDDの勉強もしたいです。

参考