【DAY17】フリーワード検索、カテゴリ検索後のページネーションについて(Laravel)

## はじめに
私はLaravelでQ&Aサイトを作成しており、フリーワード検索機能や、カテゴリ検索機能を作っているのですが、検索後の画面で次ページへのリンクを押すと検索前の質問一覧ページに戻ってしまうことに気づきました。このエラーを解決する中で学んだことをここに残します。

## Laravelにおけるページネーション
Laravelのページネーションはクエリビルダ、Eloquentと統合されており、簡単に実装することができます。
最も簡単な方法はpaginateメソッドを使うことです。引数はページごとに表示するアイテムの数です。
```QuestionController.php
public function index(Question $question)
{
    return view('questions.index')->with(['questions' => $question->paginate(5)]);
}
```

私の場合は、質問を作成順に並べたかったので、モデルにメソッドを記述してそれを使用しました。
```Question.php
public function scopeGetPaginateByLimit($query, int $limit_count = 5)
{
    return $query->orderBy('created_at', 'DESC')->paginate($limit_count);
}
 ```

 ```QuestionController.php
 public function index(Question $question)
{
    return view('questions.index')->with(['questions' => $question->getPaginateByLimit()]);
}
```

## カテゴリ検索機能について
カテゴリ検索機能の処理は以下のように記述しました。
```QuestionController.php
public function categorySearch(Request $request, Question $question)
{
    if ($request->has('categories')) {
        $categories = $request->input('categories');
        $selectedCategoryNames = Category::whereIn('id', $categories);
        $questions = $question->whereHas('categories', function ($query) use ($categories) {
            $query->whereIn('categories.id', $categories);
        });
        $questions = $questions->getPaginateByLimit();
        return view('questions.category-search')->with(['questions' => $questions, 'selectedCategoryNames' => $selectedCategoryNames]);
    }
    else {
        return redirect('/');
    }
}
```
検索のビューはこんな感じ（一部抜粋）
```index.blade.php
<form action="/search/category" method="GET">
    @foreach ($categories as $category)
        <div>
            <input type="checkbox" name="categories[]" value="{{ $category->id }}" />
            <label>
                {{ $category->name }}
            </label>
        </div>
    @endforeach
    <button type="submit">検索</button>
</form>
```
## エラーの原因
はじめに検索後の画面で次ページへのリンクを押すと検索前の質問一覧ページに戻ってしまうと書きましたが、それは
次ページのリンクを押した際にカテゴリ検索の検索条件がリセットされてelse以降の処理が行われているからでした。
このエラーを解消するために、appendsメソッドを使用しました。appendsメソッドは、クエリ文字列をページネーションリンクに追加できます。
```QuestionController.php
public function categorySearch(Request $request, Question $question)
{
    if ($request->has('categories')) {
        $categories = $request->input('categories');
        $selectedCategoryNames = Category::whereIn('id', $categories);
        $questions = $question->whereHas('categories', function ($query) use ($categories) {
            $query->whereIn('categories.id', $categories);
        });
        $questions = $questions->getPaginateByLimit()->appends(['categories' => $categories]); // 追加
        return view('questions.category-search')->with(['questions' => $questions, 'selectedCategoryNames' => $selectedCategoryNames]);
    }
    else {
        return redirect('/');
    }
}
```
これで検索後のページネーションもうまく動作するようになりました。
フリーワード検索機能についても同様にappendsメソッドを加えることで解決しました。

appends関数を追加していない状態でddコマンドで$questionを確認すると...

![スクリーンショット 2024-09-26 0.32.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818045/04f1cea1-d2f1-3a8b-8fb8-4b4e01c37f0e.png)

クエリが空になっています。
appends関数を追加してから確認すると...
![スクリーンショット 2024-09-26 0.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818045/ced596f1-2533-00e1-4893-56239c1a86cf.png)
検索したカテゴリの情報が入っています。
これでページネーションリンクにもクエリを渡せるみたいですね。