【Laravel】いろいろ見たけどリポジトリパターンの実装ができなかった初心者のためにとりあえず実装するまでをシンプルに書く

## 3行で

- UserのModelに紐づいたリポジトリパターンを実装する
- **コントローラではModelにタッチしない**ということを意識する
- 5つのファイルをいじる

## リポジトリファイルを作る

ディレクトリ `/app` の中に `Repositories` というディレクトリを作り、さらにその中に `User` というディレクトリを作り、この中にファイルを2つ作ります（この辺の構成は正直自由ですが）。

- **/app/Repositories/User/UserRepository.php**（実装ファイル）
- **/app/Repositories/User/UserRepositoryInterface.php**（インターフェイス）

この2つのファイルでModelを経由してDBにアクセスして、データを持ってきたりcreateしたりupdateしたりします。
今回はUser Modelに紐づくリポジトリパターンを作ります。つまりこれらを使ってUserのデータを持ってきたり更新したりします。コントローラではなく、これらのファイルで行うことになります。

### 1. 実装クラス

```php:UserRepository.php
<?php

// Modelに紐づく2つのメソッド以外はコピペのような感覚で書いちゃって構わないです

namespace App\Repositories\User;

// Modelにアクセスする旨を書く
use App\User;

class UserRepository implements UserRepositoryInterface
{
  protected $user;

    /**
    * @param object $user
    */

  public function __construct(User $user)
  {
      $this->user = $user;
  }

  // 名前に紐づくUserのデータを1件持ってくる
  public function getUser($name)
  {
    return $this->user->where('name', $name)->first();
  }

  // 後述のコントローラから $request を受け取って、中に入った名前とメールアドレスでユーザーを作る
  public function createUser($request)
  {
    return $this->user->create([
      'name' => $request['name'],
      'email' => $request['email'],
    ]);
  }
}
```

その他のメソッドは上記を応用して書いてみてください！

### 2. インターフェース

```php:UserRepositoryInterface.php
<?php

// 上の実装クラスに書いた、Modelに紐づく2つのメソッドを書いて使えるようにします

namespace App\Repositories\User;

interface UserRepositoryInterface
{
  public function getUser($name);

  public function createUser($request);
}
```

## ServiceProviderに登録する

`AppServiceProvider.php` を編集する。
**ここにリポジトリのファイルを使うために登録するイメージです。**
もしエラーが出たら以下の記事も見てみてください。

[【Laravel】リポジトリパターン実装におけるエラー Target [App\Repositories\UserRepositoryInterface] is not instantiable while building
](https://qiita.com/antk/items/38971fba1de4e6872b82)

```php:AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */

    /**
     * Bootstrap any application services.
     *
     * @return void
     */

    public function boot()
    {
        //
    }

    // インターフェースと実装クラスを登録
    public function register()
    {
        // 本記事ではタッチしませんが記事用のリポジトリも登録しておきます
        $this->app->bind(
            \App\Repositories\Article\ArticleRepositoryInterface::class,
            \App\Repositories\Article\ArticleRepository::class
        );
        $this->app->bind(
            \App\Repositories\User\UserRepositoryInterface::class,
            \App\Repositories\User\UserRepository::class
        );
    }
}
```

## コントローラでリポジトリを呼び出す

```php:UserController.php
<?php

namespace App\Http\Controllers;

// リポジトリを使うと宣言
use App\Repositories\User\UserRepositoryInterface;

// コントローラではModelにタッチしない
// use App\Models\User;

use Illuminate\Http\Request;

class UserController extends Controller
{
    // リポジトリ
    protected $UserRepository;

    public function __construct(
　　    // リポジトリ
        UserRepositoryInterface $userRepository
    )
    {
　　    // リポジトリ
        $this->UserRepository = $userRepository;
    }

    // 中略

    public function show($name)
    {
        // リポジトリのメソッドに引数を渡して呼び出す
        $user = $this->UserRepository->getUser($name);

        return view('users.show', [
            'user' => $user,
        ]);
    }

    public function store($request)
    {
        // フォームから受け取った $request をリポジトリのメソッドに渡し、Userデータを作る
        $this->UserRepository->createUser($request);

        return redirect()->route('home');
    }
}
```

以上です。
データが渡っているかがわからない、うまくいかない場合は `dd($request)` などを使って検証してください！