2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel7】ユーザーをキーワード検索する

Last updated at Posted at 2020-07-20

#はじめに
Laravel7の認証機能で登録したユーザーについて、キーワード検索できるページを作成します。

#環境
XAMPP環境でLaravelが使えるように設定してあります。

  • Windows10 Pro 64bit
  • PHP 7.3.18
  • Laravel 7.12.0
  • MariaDB 10.1.32

※認証機能でユーザーを登録したり、管理者を追加したりの一連の流れは過去記事をご覧ください。

#要件

  • 管理者のhomeに検索フォームを設置する。
  • デフォルトの状態(アクセス直後)は全てのユーザーを表示する。
  • 検索フォームに何も入っていないで検索した場合、全てのユーザーを表示する。
  • キーワードは名前またはメールアドレスの部分一致で検索する。
  • キーワードを半角または全角のスペースで区切った場合、AND検索とする。
  • 検索結果は10件毎にページネーションする。

Account_Manager.png

#実装

##コントローラ

app/Http/Controllers/Admin/HomeController.php
<?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

resources/views/admin/home.blade.php
@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() とします。

#参考サイト

2
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?