Laravel
リポジトリパターン
LaravelDay 17

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

More than 1 year has passed since last update.

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


リポジトリパターンとは

データの操作に関連するロジックをビジネスロジックから切り離し、抽象化したレイヤに任せることで保守や拡張性を高めるパターンです。

(必ずしもDB操作のロジックのみを留めるパターンというわけではないそうです。)

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


  • テストがしやすくなる

  • DBエンジンの変更に対応しやすくなる

  • データ操作のロジックが1箇所にまとまり、管理しやすくなる

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


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

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

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


php

.

├── 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の勉強もしたいです。


参考


その他

bmf-tech.com