【Laravel】複数条件で検索する

## 前提
ブログ記事に対して、「タイトル」「ペンネーム」「カテゴリ」「投稿日(期間)」の複数の条件で検索をかけたい。

## 流れ
①ブレードで検索フォームを作る。ボタン押下で、フォームの入力内容を同じ画面にGET送信させる。
②コントローラーの、同じブレードを表示させているメソッド(今回はindexメソッド)に、検索処理を加える。検索し加工した値をブレードに返すようにする。
③モデルに、検索処理を書く。今回は、検索ロジックを使いまわしたいので、コントローラーではなくモデルに書いた。このモデルのメソッドを、コントローラーで呼び出している。

```search.blade.php
{{-- 記事検索 --}}
<div class="w-4/5 mt-10 mx-auto">
    <form class="flex flex-wrap" method="get" action="{{route('index')}}">
        <div class="flex justify-start items-center w-1/2 mt-6">
            <div class="">
                <label class="block text-gray-700 font-bold text-right mb-1 mb-0 pr-4" for="inline-full-name">
                    タイトル
                </label>
            </div>
            <div class="w-4/5">
                <input class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" id="inline-full-name" type="text" name="title" placeholder="日々の記録">
            </div>
        </div>
        <div class="flex justify-end items-center w-1/2 mt-6">
            <div class="">
                <label class="block text-gray-700 font-bold text-right mb-1 mb-0 pr-4" for="inline-penname">
                    ペンネーム
                </label>
            </div>
            <div class="w-4/5">
                <input class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" id="inline-penname" type="text" name="penname" placeholder="ペンタネム子">
            </div>
        </div>
        <div class="flex justify-start items-center w-1/2 mt-6">
            <div class="">
                <label class="block text-gray-700 font-bold text-right mb-1 mb-0 pr-4" for="category">
                    カテゴリ
                </label>
            </div>
            <div class="w-4/5">
                <select class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" id="category" name="category">
                    @foreach ($categories as $category)
                    <option>{{ $category->name }}</option>
                    @endforeach
                </select>
            </div>
        </div>
        <div class="flex justify-end items-center w-1/2 mt-6">
            <div class="">
                <label class="block text-gray-700 font-bold text-right mb-1 mb-0 pr-4" for="category">
                    投稿日
                </label>
            </div>
            <div class="w-4/5 flex">
                <input class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 mr-3 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" type="date" name="from" placeholder="from_date" value="">
                <span class="mx-3">~</span>
                <input class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 ml-3 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500" type="date" name="until" placeholder="until_date" value="">
            </div>
        </div>
        <div class="flex justify-end items-center w-1/2 mt-6">
        </div>
        <div class="flex justify-end items-center w-1/2 mt-6">
            <div>
            <button class="inline-block bg-blue-500 text-white py-2 px-4 rounded w-15 text-center shadow-md" type="submit">
                検索
            </button>
            </div>
        </div>
    </form>
</div>
```

```ArticleController.php
// 表示
public function index(Request $request)
{
    $categories = Category::all();
    $article = new Article;
    // Articleモデルのsearchメソッドを呼び出し
    $articles = $article->search($request);
    $lastItem = $articles->lastItem();
    $total = $articles->total();
    return view('index', compact('categories', 'articles', 'lastItem', 'total'));
}
```

```Article.php
$query = Article::query();

if ($request->has('title') && $request->title !== null) {
    $query->where('title', 'like', '%' . $request->title . '%');
}

if ($request->has('penname') && $request->penname !== null) {
    $penname = $request->penname;
    $query->with(['profile'])->whereHas('profile', function ($q) use ($penname) {
        $q->where('profiles.penname', 'like', '%' . $penname. '%');
    });
}

if ($request->has('category') && $request->category !== null) {
    $category = $request->category;
    $query->with(['category'])->whereHas('category', function ($q) use ($category) {
        $q->where('categories.name', $category);
    });
}

if ($request->has('from') && $request->from !== null) {
    $fromDate = Carbon::parse($request->from);
    $query->whereDate('created_at', '>=', $fromDate);
}

if ($request->has('until') && $request->until !== null) {
    $untilDate = Carbon::parse($request->until);
    $query->whereDate('created_at', '<=', $untilDate);
}

// 最初、withを書いていなかったら、検索ロジックが動かなかった。リレーション先のテーブルから検索する場合、withメソッドが必要。
$articles = $query->with(['profile', 'category'])->paginate(10);

return $articles;

```