Laravelでログイン機能付きサイト作成 with XAMPP(4/4) 検索機能編

## 目標
**`Laravel`でユーザー検索機能を持ったサイトを作成する。**

## 前回の記事
[Laravelでログイン機能付きサイト作成 with XAMPP(3/4) ユーザー情報変更機能編](https://qiita.com/kaitaku/items/d7faf24a68ba933607f0)


## 検索機能作成
検索内容はテーブルに登録されているユーザー情報の部分一致。
**`検索画面　→　検索結果画面`**の構成で作成していく。

### 検索画面

コントローラーを下記のコマンドで作成する。

```
 $ php artisan make:controller User/SearchController
```

今回の検索機能では、検索ワードから部分一致の値をすべて検索してから結果を返すのではなく、あらかじめ検索するカテゴリー、カラムを指定する。
そのため、コントローラーでViewに渡すカテゴリーを記入する。

```(プロジェクト名)\app\Http\Controllers\User\SearchController.php
<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class SearchController extends Controller
{
    public function search()
    {
    	$category_name = ['ID','NAME','COMMENT'];
        return view('user/search',['NAME' => $category_name]);
    }
}
```

表示するページでは、コントローラーから渡された検索するカテゴリーの選択機能と、そのカテゴリーで検索したい内容の検索ワードを作成する。

```(プロジェクト名)\resources\views\user\search.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    ユーザー検索
                </div>
                <div class="card-body">
                	<p>検索したいユーザーの情報を入力してください。</p>
                	 <div class="search">
                        <form method="post" action="result">
                        	<div class="category">
                        		<p>検索項目: </p>
                        		<select name="search_category">
                        			<option value = "" selected>選択してください</option>
                        			@for($i = 0; $i < 3; $i++)
                        			<option value = "{{ $NAME[$i] }}">{{ $NAME[$i] }}</option>
                        			@endfor
								</select>
                        	</div>
                        	<div class="word">
                        		<p>検索ワード: </p>
                        		<input type="text" name="search_word">
                        	</div>
							<input type="submit" value="検索する">
                            @csrf
                        </form>
                    </div>
                	<div>
                        <input type="button" value="戻る" onclick="history.back()">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

@endsection
```

検索するカテゴリーは`<select>`で選択できるようにし、各項目をそれぞれ記入するのではなく、`@foreach`を利用して記述する。

そして、ルーティング処理を追記。

```(プロジェクト名)\routes\web.php
Route::get('/home/search','User\SearchController@search');
```

遷移元の`home.blade.php`に今回作成したページへのリンクを忘れずに追加。

```(プロジェクト名)\resources\views\home.blade.php
<a href="home/user">ユーザー検索</a>
```

以上のコードで以下のページが完成する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/f03a8dde-66e7-67d9-4401-1aefa421e002.png" width="700px">

### 検索結果画面

コントローラーを下記のコマンドで作成。

```
 $ php artisan make:controller User/ResultController
```

このコントローラーには、`検索画面で選択されたカテゴリー`,`検索画面で入力されたワード`,`前の2つを元にテーブルに検索をかけた結果`を入力する。

```(プロジェクト名)\app\Http\Controllers\User\ResultController.php
<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;

class ResultController extends Controller
{
    public function result(Request $request)
    {
        $category = $request -> input('search_category');
        $word = $request -> input('search_word');
        $search_data = array(
        	'category' => $category,
        	'word' => $word
        );
        $user_data = User::where($category, 'like', "%$word%") -> get();
        return view('user/result',['Search' => $search_data, 'User' => $user_data]);
    }
}
```

どんな値で検索したかをわかりやすくするために、検索結果だけでなく、選択したカテゴリーと検索ワードも渡す。
部分一致は**`where(カラム名, 'like', "%検索ワード%")`**で検索を行える。

表示するページでは、コントローラーから渡された値を表示するだけで良い。

```(プロジェクト名)\resources\views\user\result.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    検索結果
                </div>
                <div class="card-body">
                	 <div class="result">
                        <form method="post" action="search">
                        	<div class="category">
                        		検索項目: {{ $Search['category'] }}
                        	</div>
                        	<div class="word">
                        		検索ワード: {{ $Search['word'] }}
                        	</div>
                        	@if (isset($User))
                        	<table>
                                <tr>
                                    <th>ID</th>
                                    <th>NAME</th>
                                    <th>COMMENT</th>
                                </tr>
                                @foreach($User as $Data)
                                <tr>
                                    <td>{{ $Data['id'] }}</td>
                                    <td>{{ $Data['name'] }}</td>
                                    <td>{{ $Data['comment'] }}</td>
                                </tr>
                                @endforeach    
                            </table>
                            @else
                        	<p>検索条件に一致するユーザーは登録されていません</p>
                        	@endif
                        	<input type="submit" value="検索画面にもどる">
                            @csrf
                        </form>
                    </div>
                    <div class="to_home">
                    	<input type="button" value="ホーム画面へ" onclick="/home">
                	</div>
                </div>
            </div>
        </div>
    </div>
</div>

@endsection

```

検索結果が1つとは限らないので、ここでも`@foreach`を利用して、部分一致で合致したユーザーを全て表示できるようにした。

検索結果画面は`POST`での遷移だが、`GET`でアクセスされた際のルーティング処理を記入。

```(プロジェクト名)\routes\web.php
Route::get('/home/result','User\SearchController@search');
Route::post('/home/result','User\ResultController@result');
```

以上のコードで以下のページが完成する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/ec426ddc-6c8e-33a5-4e92-f287e467195f.png" width="700px">

### 検索結果画面 → 検索画面

ここでも検索結果画面での値を保持して、検索画面に戻れるようにする。

そのためには、`result.blade.php`で渡された値を返せるようにする必要がある。

```(プロジェクト名)\resources\views\user\result.blade.php
@endif
<input type="hidden" value="{{ $Search['category'] }}" name="search_category" >
<input type="hidden" value="{{ $Search['word'] }}" name="search_word" >
<input type="submit" value="検索画面にもどる">
@csrf
```

そして、検索画面のコントローラー、`SearchController.php`では、`result.blade.php`から渡された値を受け取って、検索画面に渡せるようにする。

```(プロジェクト名)\app\Http\Controllers\User\SearchController.php
public function return_search(Request $request)
    {
        $category = $request -> input('search_category');
        $word = $request -> input('search_word');
        $search_data = array(
        	'category' => $category,
        	'word' => $word
        );
    	$category_name = ['ID','NAME','COMMENT'];
        return view('user/search',['NAME' => $category_name, 'Search' => $search_data]);
    }
```

検索画面、`search.blade.php`では、検索結果画面から遷移した時に表示する内容と前回入力された値を表示できるようにする。

```(プロジェクト名)\resources\views\user\search.blade.php
　　//　中略
<form method="post" action="result">
	<div class="category">
		<p>検索項目: </p>
		<select name="search_category">
		@if(isset($Search))
			@for($i = 0; $i < 3; $i++)
				@if($Search['category'] === $NAME[$i])
				<option value = "{{ $NAME[$i] }}" selected>{{ $NAME[$i] }}</option>
				@else
				<option value = "{{ $NAME[$i] }}">{{ $NAME[$i] }}</option>
				@endif
			@endfor
		@else
			<option value = "" selected>選択してください</option>
			@for($i = 0; $i < 3; $i++)
			<option value = "{{ $NAME[$i] }}">{{ $NAME[$i] }}</option>
			@endfor
		@endif
		</select>
	</div>
	<div class="word">
		<p>検索ワード: </p>
		@if(isset($Search))
			<input type="text" name="search_word" value="{{ $Search['word'] }}">
		@else
			<input type="text" name="search_word">
		@endif
	</div>
	<input type="submit" value="検索する">
    @csrf
</form>
```

`SearchController.php`から渡される`$Search`があるかないかで検索結果画面からの遷移かどうかを判断するため、**`@if(isset($Search))`**を使用する。
`<option>`タグに**`selected`**を付ける事でその値を選んだ状態にできる。


ルーティング処理を記入して、実際に確かめてみる。

```(プロジェクト名)\routes\web.php
Route::post('/home/search','User\SearchController@return_search');
```

## おわりに
以上で`Laravel`の学習を終える。
基本的な機能であれば作成できるようになったが、まだまだ使いきれていない機能もあるので、引き続き学習を進めていく。

## Tips
`Laravel`の学習で得た知見や小技を記事にしたのをここにまとめる。

- [Laravelの認証機能をカスタマイズしてデータベースにレコードを作成する](https://qiita.com/kaitaku/items/af919955a7e8de898a20)
- [Laravelのバリデーションにおける基礎をまとめる](https://qiita.com/kaitaku/items/503b91c40baa6ba45ec3)
- [Laravelでuniqueの対象から自分自身の値を外す](https://qiita.com/kaitaku/items/d38e9e498b094405dede)
- [Laravelのバリデーションでエラー時の遷移先を制御する](https://qiita.com/kaitaku/items/43584ed834853e402786)
- [Laravelでcreateを実行してもカラムの値がNULLになってしまうときの解決策](https://qiita.com/kaitaku/items/1334f8bdd9917228c104)
- [LaravelでSwift_TransportExceptionが発生した時の対処法(Gmail編)](https://qiita.com/kaitaku/items/66ee58c3b4ff766073ab)
- [LaravelでAuthモデルを呼び出す時って、なんでuse App/Authじゃないの?](https://qiita.com/kaitaku/items/d250a4383cddc7bbcebd)
- [Laravelの確認画面から戻って入力画面に値を渡すシンプルな方法](https://qiita.com/kaitaku/items/55bc4e0a666669bb4b37)
- [Laravelでチェックボックスを使用した検索フォームの作り方](https://qiita.com/kaitaku/items/7eadcc88332c337b2d5c)
- [【Laravel】SplFileObjectでCSVファイルのデータを読み込んでDBに反映する](https://qiita.com/kaitaku/items/b85a32cec244e9fed1be)
## 参考資料
- [【Laravel】自画面遷移時にセレクトボックスの選択値を保持させる - Qiita](https://qiita.com/C_HERO/items/40e6a551a24a09a9053d)
- [Laravelでwhere検索する時、部分一致を用いても検索できない](https://qiita.com/Lil_Ryo/items/f344fb84b59622a67b7b)