l5-repository を使うのをやめた話

# TLDR;
Laravel にはリポジトリパターンを適用しやすい l5-repository というライブラリがある。
https://github.com/andersao/l5-repository
しばらくこれをつかっていたけど、実は無駄なことをしていたんじゃないかと思い、使わないでリポジトリパターン的なことができるよという紹介というか雑なメモ。
現時点でのバージョンは laravel 5.6

# リポジトリパターンを l5-repository 無しでやる
私はリポジトリパターンは DI によってテストをしやすくするために適用していた。
まずは l5-repository だとどのように書くか大まかに書く。

## l5-repository での流れ

+ make:repository でマイグレーション、インターフェースと具象クラス、エンティティを作成する
+ リポジトリサービスプロバイダーに登録する
+ リポジトリを利用した実装をする
+ テストを書く

コードは簡単にこんな感じ

```php:HogeRepository.php
interface HogeRepository extends RepositoryInterface
{
    //
}
```

```php:HogeRepositoryEloquent.php
class HogeRepositoryEloquent extends BaseRepository implements HogeRepository
{
    /**
     * Specify Model class name
     *
     * @return string
     */
    public function model()
    {
        return Hoge::class;
    }



    /**
     * Boot up the repository, pushing criteria
     */
    public function boot()
    {
        $this->pushCriteria(app(RequestCriteria::class));
    }
}
```

```php:Hoge.php
class Hoge extends Model implements Transformable
{
    use TransformableTrait;

    protected $guarded = [
        'id',
    ];
}
```

```php:RepositoryServiceProvider.php

    public function register()
    {
        $repositories = [
            // ...
            \App\Repositories\HogeRepository::class, // 追加
            // ....
        ];

        foreach ($repositories as $repository) {
            $this->app->bind($repository, $repository . 'Eloquent');
        }
    }
```

```php:HogeController.php
protected $hogeRepository;

public function __construct(HogeRepository $hogeRepository)
{
    $this->hogeRepository = $hogeRepository;
}

public function index(Request $request)
{
    return $this->hogeRepository->paginate();
}
```

```php:HogeControllerTest.php
public function testHogeIndex()
{
    $hoge = factory(Hoge::class)->make();
    $mock = Mockery::mock(HogeRepository::class);
    $this->app->instance(HogeRepository::class, $mock);
    $mock->shouldReceive('paginate')->andReturn($hoge);

    $this->call('GET', '/hoge');
    $this->assertResponseOk();
    // レスポンスのテスト
}
```

こんな感じ。


ただ、こういう運用していて interface の旨味はなくて煩雑になった。プロバイダとか登録するの面倒だし。
これ、素の laravel でもどうやら似たことできる。すでに Eloquent がファサードなのでモックできるし。

## 素の laravel での書き方

```php:Hoge.php
class Hoge extends Model
{
    protected $guarded = [
        'id',
    ];
}
```

```php:HogeController.php
protected $hogeRepository;

public function __construct(Hoge $hogeRepository)
{
    $this->hogeRepository = $hogeRepository;
}

public function index(Request $request)
{
    return $this->hogeRepository->paginate();
}
```

```php:HogeControllerTest.php
public function testHogeIndex()
{
    $hoge = factory(Hoge::class)->make();
    Hoge::shouldReceive('paginate')->andReturn($hoge);

    $this->call('GET', '/hoge');
    $this->assertResponseOk();
    // レスポンスのテスト
}
```

インターフェースつくらないからプロバイダの登録いらない。エンティティだけで十分な気がした。
ポイントはファサードをそのまま利用せず、コントローラーではコンストラクタでインスタンスを要求している点。


# RequestCriteria について

あとひとつ有用な機能の RequestCriteria については別のライブラリ入れて解決した。

l5-repository では searchableField を指定すると、下記のようなリクエストを解析して検索クエリを発行してくれる
`http://prettus.local/users?search=name:John;email:john@gmail.com&searchFields=name:like;email:=`
これは `name like 'John' and email = 'john@gmail.com'` という検索クエリを追加する。

自分は pimpable というライブラリを入れた。
https://github.com/jedrzej/pimpable
同じようにリクエストのパラメタから素のEloquentに対して検索クエリを追加してくれる

検索可能なフィールドを指定してあげて、検索したいときに pimp を呼ぶだけ

```php:Hoge.php
class Hoge extends Model
{
    use PimpableTrait;
    
    protected $guarded = [
        'id',
    ];
    
    public $searchable = ['name', 'email'];
}

```

```php:HogeController.php
Hoge::pimp()->paginate();
```

`http://localhost/hoge?name=%John%&email=john@gmail.com`
このリクエストで上記と同じ結果になる