LaravelでService層、Repository層を取り入れる方法とその必要性を簡潔に語る

#はじめに

Laravelでアプリケーションを実装するにあたり、Controllerがゴチャつくケースがよくあると思います。
例えばDBからデータを取得しフロントに表示するという単純な作業にしても、データを整形したりと色々コードを書いていく必要があります。
そうしているうちに一つのメソッドだけで数十行、数百行にもなってしまうこのようなControllerをFat Controllerと呼んだりします。
こうなってしまうとコードの可読性も悪いですし、拡張性が低いです。
この問題を解決するには役割分担をすることが最適解かと思われます。
今回はその方法について記述していきたいと思います。

#やりたいこと
今回はフロントからリクエストしたidを使いhogeモデルからレコードを取得しjsonでフロントに返却するケースを想定。

フロントからリクエスト→Controller→Service→Repository→Model
という流れでこのユースケースを実現させる方法を記述します。


#それぞれの役割
* Controller
フロントと、ビジネスロジックで取得したデータの橋渡しの役割を担います。
今回はリクエストされたidを渡し、取得したデータをフロントに返す役割として使用します。

* Service
データの永続化に関わらないビジネスロジックをここに書きます。
具体的にはモデルのユースケースを書いていきます。(crud)
また今回の例でいうと、json整形のような取得したデータを加工しControllerに値を返す処理をここで実装ます。

* Repository
データの永続化に関わるビジネスロジック（データの保存などの操作)はここに書きます。
今回はリクエストされたidを使いデータを取ってくるロジックをここで実装します。

#appディレクトリ配下の構成
下記の構成で作っていきたいと思います。

```
app
├ Console
├ Exceptions
├ Http
│ ├ Controllers
│ │ └ HogeController.php →追加
│ ├ Middleware	
│ └ Requests
├ Models→追加
│ ├ Hoge.php→追加
├ Providers
│ ├ AppServiceProvider.php
├ Repositories →追加
│ ├ HogeRepository.php
│ └ HogeRepositoryInterface.php
└ Services →追加
　 ├ HogeService.php →追加
```

#準備

##Hogeテーブルの準備

```
$ php artisan make:migration create_hoges_table
$ php artisan migrate
```


##必要なディレクトリ及びファイルを追加
前項で「→追加」と書いている部分については自分で作成します。
ControllerとModelは以下コマンドで作成。

```
$ php artisan make:controller HogeController
$ php artisan make:model Hoge
```




##AppServiceProviderに登録
サービスとリポジトリを使えるようにします。（正確にはDIしたいときのみ登録が必要）
registerメソッド内に2行追記。

```AppServiceProvider.php

public function register()
    {
        $this->app->bind('App\Services\HogeService');
        $this->app->bind('App\Repositories\HogeRepositoryInterface', 'App\Repositories\HogeRepository');
    }

```

#実装

##Repository
まずはインターフェイスを作成。

```HogeepositoryInterface.php
<?php

namespace App\Repositories;

interface HogeRepositoryInterface
{
    public function find($id);
}
```

行き→Service渡からってきたidを使いデータを取得する。
帰り→Modelから取得したデータをServiceに返す。

```HogeRepository.php
<?php

namespace App\Repositories;

use App\Models\Hoge;

class HogeRepository implements HogeRepositoryInterface
{
    public function find($id)
    {
        return Hoge::find($id);
    }
```

##Service
行き→Controllerから渡ってきたidをRepositoryに渡す。
帰り→Repositoryから返ってきたデータをjosn整形しControllerに返す。

```HogeService.php
<?php

namespace App\Services;

use App\Repositories\HogeRepositoryInterface as HogeRepository;

class HogeService
{
    public function __construct(HogeRepository $hogeRepo)
    {
        $this->hogeRepositry = $hogeRepo;
    }

    public function find($id)
    {
        $hoge = $this->hogeRepositry->find($id);
        $respons = json_encode($hoge);
        return $respons;
    }
```

##Controller
行き->フロントからリクエストされたidをServiceに渡す。
帰り->Serviceから返ってきた整形されたデータをフロントに返す。

```HomeController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\HogeService;

class HogeController extends Controller
{
    public function __construct(HogeService $hogeService)
    {
        $this->hogeService = $hogeService;
    }

    public function find(Request $request)
    {
        return $this->hogeService->find($request->id)
    }
}

```

#最後に
上記の実装で、フロントからリクエストした値を使いDBからレコードを取得する一連の流れを、役割分担しつつ実装できます。