#はじめに
Laravel7の認証機能で登録したユーザーについて、キーワード検索できるページを作成します。
#環境
XAMPP環境でLaravelが使えるように設定してあります。
- Windows10 Pro 64bit
- PHP 7.3.18
- Laravel 7.12.0
- MariaDB 10.1.32
※認証機能でユーザーを登録したり、管理者を追加したりの一連の流れは過去記事をご覧ください。
- 【Laravel7でユーザー認証_1】基本のき
- 【Laravel7でユーザー認証_2】ユーザー認証を日本語化
- 【Laravel7でユーザー認証_3】ユーザー認証をメールアドレスからユーザー名に変更する
- 【Laravel7でユーザー認証_4】パスワード変更フォームを作成する
- 【Laravel7でユーザー認証_5】ユーザーを倫理削除(SoftDelete)する
- 【Laravel7でユーザー認証_6】ユーザーの情報を表示・変更する設定画面を作成する
- 【Laravel7でユーザー認証_7】会員登録時にメール認証を行う
- 【Laravel7でユーザー認証_8】メールアドレス変更時にメール認証を行う
- 【Laravel7でユーザー認証_9】マルチ認証機能を使って管理者を作成する
- 【Laravel7でユーザー認証_10】マルチ認証機能で作成した管理者のパスワード変更・リセット機能を追加する
#要件
- 管理者のhomeに検索フォームを設置する。
- デフォルトの状態(アクセス直後)は全てのユーザーを表示する。
- 検索フォームに何も入っていないで検索した場合、全てのユーザーを表示する。
- キーワードは名前またはメールアドレスの部分一致で検索する。
- キーワードを半角または全角のスペースで区切った場合、AND検索とする。
- 検索結果は10件毎にページネーションする。
#実装
##コントローラ
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:admin');
}
public function redirectIndex()
{
return redirect(route('admin.home'));
}
public function index(Request $request)
{
$q = $request->input('q'); //フォームの入力値を取得
//検索キーワードが空の場合
if (empty($q)) {
$users = User::paginate(10); //全ユーザーを10件/ページで表示
//検索キーワードが入っている場合
} else {
$_q = str_replace(' ', ' ', $q); //全角スペースを半角に変換
$_q = preg_replace('/\s(?=\s)/', '', $_q); //連続する半角スペースは削除
$_q = trim($_q); //文字列の先頭と末尾にあるホワイトスペースを削除
$_q = str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $_q); //円マーク、パーセント、アンダーバーはエスケープ処理
$keywords = array_unique(explode(' ', $_q)); //キーワードを半角スペースで配列に変換し、重複する値を削除
$query = User::query();
foreach($keywords as $keyword) {
//1つのキーワードに対し、名前かメールアドレスのいずれかが一致しているユーザを抽出
//キーワードが複数ある場合はAND検索
$query->where(function($_query) use($keyword){
$_query->where('name', 'LIKE', '%'.$keyword.'%')
->orwhere('email', 'LIKE', '%'.$keyword.'%');
});
}
$users = $query->paginate(10); //検索結果のユーザーを10件/ページで表示
}
return view('admin.home', compact('users', 'q'));
}
}
検索文字列に「yamada taro」と入力した場合、名前かメールアドレスに「yamada」という文字列が含まれているユーザーを抽出し、さらにその中で、名前かメールアドレスに「taro」という文字列が含まれているユーザーを抽出するという仕様になります。
この、(A or B) and (C or D) の条件での検索は、useを使ってクロージャへ変数を渡してやることで実現します。(参考:Eloquent/QueryBuilderによるAnd検索とOr検索の複合)
###view
@extends('layouts.admin.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<form method="GET" action="{{ route('admin.home') }}">
<div class="form-row">
<div class="col">
<input id="q" type="text" class="form-control" name="q" value="{{ $q }}" autocomplete="q" autofocus placeholder="{{ __('Name or Email') }}">
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">
{{ __('Search') }}
</button>
</div>
</div>
</form>
</div>
<div class="col-md-12">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
@if(!empty($users))
{{ __('SearchResult') }} : {{ __('SearchCount', ['num' => $users->total()]) }}
<div class="card" style="margin-bottom: 20px;">
<div class="card-header">{{ __('UserList') }}</div>
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>{{ __('ID') }}</th>
<th>{{ __('Name') }}</th>
<th>{{ __('E-Mail Address') }}</th>
<th>{{ __('CreateDate') }}</th>
<th>{{ __('UpdateDate') }}</th>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->created_at->format('Y/m/d') }}</td>
<td>{{ $user->updated_at->format('Y/m/d') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="paginate">
{{ $users->appends(Request::only('q'))->links() }}
</div>
@endif
</div>
</div>
</div>
@endsection
$users
に渡された値を、foreach
で展開します。
$users->total()
で結果の合計件数が表示できます。
ページネーションで2ページ目以降のページにもキーワードを引き継ぎさせたいので、 ページネーション部分は appends
メソッドでクエリ文字列(q)を指定し $users->appends(Request::only('q'))->links()
とします。
#参考サイト