31
32

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.

【Laravel】検索機能の実装

Last updated at Posted at 2019-12-24

#laravelで検索機能の実装

#要件定義

今回はユーザー一覧から検索機能を実装する。
ユーザーの管理対象項目は名前、年齢、性別

#データベース設計

プロジェクト名:serch
モデル名:User
テーブル名:users

#プロジェクトファイルの作成

$ composer create-project --prefer-dist laravel/laravel='5.8' serch

#.envファイルにデータベースの設定

#database.sqliteファイルの作成

#Userモデルとマイグレーションファイルを作成

$ php artisan make:model User -m
Model created successfully.
Created Migration: 2019_12_21_043638_create_users_table

#マイグレーションファイルの修正

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('sex');
            $table->integer('age');
            $table->timestamps();
        });

#マイグレーションの実行

$ php artisan migrate
Migration table created successfully.
Migrating: 2019_12_21_043638_create_users_table
Migrated:  2019_12_21_043638_create_users_table (0.01 seconds)

#UsersControllerの作成

$ php artisan make:controller UsersController
Controller created successfully.

#usersテーブルにデータを挿入するseederファイルを作成

$ php artisan make:seeder UsersTableSeeder
Seeder created successfully.

#seederファイルに書き込むデータを記載する。

database/seeds/UsersTableSeeder.php
      DB::table('users')->insert([
        [
        'name' => '岩崎蓮',
        'age' => 34,
        'sex' => '男',
        'created_at' => new Datetime(),
        'updated_at' => new Datetime()
      ],
        [
        'name' => '町田里奈',
        'age' => 20,
        'sex' => '女',
        'created_at' => new Datetime(),
        'updated_at' => new Datetime()
      ],
        [
        'name' => '横田拓也',
        'age' => 25,
        'sex' => '男',
        'created_at' => new Datetime(),
        'updated_at' => new Datetime()
      ],
        [
        'name' => '矢野萌',
        'age' => 25,
        'sex' => '女',
        'created_at' => new Datetime(),
        'updated_at' => new Datetime()
      ],
        [
        'name' => '沼田舞',
        'age' => 31,
        'sex' => '女',
        'created_at' => new Datetime(),
        'updated_at' => new Datetime()
      ],

    ]);
    }

#DatabaseSeederに実行できるように編集

    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call(UsersTableSeeder::class);
    }

#seederの実行

$ php artisan db:seed
Seeding: UsersTableSeeder
Database seeding completed successfully.

#ルーティングの設定

route/web.php

//検索結果を表示する
Route::get('/serch','UsersController@serch');

//ユーザー一覧と検索画面
Route::get('/','UsersController@index');

#Userモデルに書き込み可能な権限を加える

app/User.php
class User extends Model
{
    //
        protected $fillable = ['name','age','sex'];
}

#コントローラーの編集

とりあえず、ユーザー一覧を取得するindexメソッドを作成

app/Http/controllers/UsersController.php
  public function index() {
      $users = User::all();
      return view('index')->with('users', $users);
    }

#全体ビューを作成

共通化するビューのフォルダとファイルを作成

$ cd resources/views
$ mkdir layouts
$ cd layouts
$ vi defalt.blade.php

defalt.blade.phpの編集

resources/views/layouts/defalt.blade.php
<!doctype html>
<html lang="ja">
  <head>
    <title>ユーザー管理</title>
  <!-- 必要なメタタグ -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>
  <body>
    <div class="container" style="margin-top:50px;">
      <ul class="nav justify-content-end">
    <li class="nav-item">
      <a class="nav-link active" href="{{ url('/')}}">検索と一覧</a>
    </li>
  </ul>
      @yield('content')
    </div>
    ...

  <!-- オプションのJavaScript -->
  <!-- 最初にjQuery、次にPopper.js、次にBootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  </body>
</html>

#indexビューを作成

resources/views/index.blade.php
@extends('layouts.defalt')

@section('content')
<h1>検索条件を入力してください</h1>
<form action="{{ url('/serch')}}" method="post">
  {{ csrf_field()}}
  {{method_field('get')}}
  <div class="form-group">
    <label>名前</label>
    <input type="text" class="form-control col-md-5" placeholder="検索したい名前を入力してください" name="name">
  </div>
  <div class="form-group">
    <label>年齢</label>
    <input type="text" class="form-control col-md-5" placeholder="年齢を入力してください" name="age" value="{{ old("name")}}">
  </div>

  <div class="form-group">
     <label>年齢の条件</label>
     <select class="form-control col-md-5" name="age_condition">
       <option selected value="0">選択...</option>
       <option value="1">以上</option>
       <option value="2">以下</option>
     </select>
   </div>

  <div class="form-group">
     <label>性別</label>
     <select class="form-control col-md-5" name="sex">
       <option selected value="0">選択...</option>
       <option value="1"></option>
       <option value="2"></option>
     </select>
   </div>

  <button type="submit" class="btn btn-primary col-md-5">検索</button>
</form>
@if(session('flash_message'))
<div class="alert alert-primary" role="alert" style="margin-top:50px;">{{ session('flash_message')}}</div>
@endif
<div style="margin-top:50px;">
<h1>ユーザー一覧</h1>
<table class="table">
  <tr>
    <th>ユーザー名</th><th>年齢</th><th>性別</th>
  </tr>
@foreach($users as $user)
  <tr>
    <td>{{$user->name}}</td><td>{{$user->age}}</td><td>{{$user->sex}}</td>
  </tr>
@endforeach
</table>
</div>
@endsection

#laravelサーバーを立ち上げて確認

$ php artisan serve --host ***.****.**.** --port 8000

こんな感じでできていれば、okです。

スクリーンショット 2019-12-22 10.16.36.png

#検索機能を実装していきます。

##検索画面を作成

resources/views/serch.blade.php
@extends('layouts.defalt')

@section('content')
<div style="margin-top:50px;">
<h1>検索結果</h1>
@if(isset($users))
<table class="table">
  <tr>
    <th>ユーザー名</th><th>年齢</th><th>性別</th>
  </tr>
  @foreach($users as $user)
    <tr>
      <td>{{$user->name}}</td><td>{{$user->age}}</td><td>{{$user->sex}}</td>
    </tr>
  @endforeach
</table>
@endif
@if(!empty($message))
<div class="alert alert-primary" role="alert">{{ $message}}</div>
@endif
</div>
@endsection

##検索メソッドを作成。コントローラーの編集

app/Http/Controllers/USersController.php
public function serch(Request $request) {
      $keyword_name = $request->name;
      $keyword_age = $request->age;
      $keyword_sex = $request->sex;
      $keyword_age_condition = $request->age_condition;

      if(!empty($keyword_name) && empty($keyword_age) && empty($keyword_age_condition)) {
      $query = User::query();
      $users = $query->where('name','like', '%' .$keyword_name. '%')->get();
      $message = "「". $keyword_name."」を含む名前の検索が完了しました。";
      return view('/serch')->with([
        'users' => $users,
        'message' => $message,
      ]);
    }

    elseif(empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 0){
          $message = "年齢の条件を選択してください";
          return view('/serch')->with([
            'message' => $message,
          ]);
    }
    elseif(empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 1){
      $query = User::query();
      $users = $query->where('age','>=', $keyword_age)->get();
      $message = $keyword_age. "歳以上の検索が完了しました";
      return view('/serch')->with([
        'users' => $users,
        'message' => $message,
      ]);
    }
    elseif(empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 2){
      $query = User::query();
      $users = $query->where('age','<=', $keyword_age)->get();
      $message = $keyword_age. "歳以下の検索が完了しました";
      return view('/serch')->with([
        'users' => $users,
        'message' => $message,
      ]);
    }
    elseif(!empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 1){
      $query = User::query();
      $users = $query->where('name','like', '%' .$keyword_name. '%')->where('age','>=', $keyword_age)->get();
      $message = "「".$keyword_name . "」を含む名前と". $keyword_age. "歳以上の検索が完了しました";
      return view('/serch')->with([
        'users' => $users,
        'message' => $message,
      ]);
    }
    elseif(!empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 2){
      $query = User::query();
      $users = $query->where('name','like', '%' .$keyword_name. '%')->where('age','<=', $keyword_age)->get();
      $message = "「".$keyword_name . "」を含む名前と". $keyword_age. "歳以下の検索が完了しました";
      return view('/serch')->with([
        'users' => $users,
        'message' => $message,
      ]);
    }
    elseif(empty($keyword_name) && empty($keyword_age) && $keyword_sex == 1){
      $query = User::query();
      $users = $query->where('sex','男')->get();
      $message = "男性の検索が完了しました";
            return view('/serch')->with([
              'users' => $users,
              'message' => $message,
            ]);
    }
    elseif(empty($keyword_name) && empty($keyword_age) && $keyword_sex == 2){
      $query = User::query();
      $users = $query->where('sex','女')->get();
      $message = "女性の検索が完了しました";
            return view('/serch')->with([
              'users' => $users,
              'message' => $message,
            ]);
    }
    else {
      $message = "検索結果はありません。";
      return view('/serch')->with('message',$message);
      }
}

#おまけ

#目的
laravelで検索機能を実装してみたが、検索時のコントローラーに書いたメソッドが長すぎるので、すっきりさせる。その際にファザードという機能を使う。

#全体的な流れ

"serch"という名称のサービスプロバイダーを作成

#プロバイダーの設定

##SerchServiceProviderを作成

$ php artisan make:provider SerchServiceProvider
Provider created successfully.

##serchクラスの登録

app/Http/Providers/SerchServiceProvider.php
    public function register()
    {
        $this->app->bind(
          'serch',
          'App\Http\Compornents\Serch'
        );
    }

#ファザードの設定

##ファザードクラスの作成

laravel/app 配下にFacadesディレクトリを作成し、その中にSerch.phpを作成

コンポーネントの登録名を取得する為のアクセサーgetFacadeAccessor()メソッドを以下のように定義します。

app/Fadades/Serch.php
<?php

namespace App\Facades;

use Illumnate\Support\Facades\Facade;

class Serch extends Facade
{
  protected static function getfacadeAccessor() {
    retrun 'serch';
  }
}

##検索メソッドをSerchクラスにまとめる

laravel/app/Http 配下に Components ディレクトリを作成し、その中にSerch.phpを作成

app/Http/Compornents
<?php

namespace App\Http\Components;

use App\User;

class Serch
{
  public static function serch($keyword_name,$keyword_age,$keyword_sex,$keyword_age_condition)
  {
          $query = User::query();

          if(!empty($keyword_name) && empty($keyword_age) && empty($keyword_age_condition)) {
          $users = $query->where('name','like', '%' .$keyword_name. '%')->get();
          $message = "「". $keyword_name."」を含む名前の検索が完了しました。";
        }

        elseif(empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 0){
              $message = "年齢の条件を選択してください";
        }
        elseif(empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 1){
          $users = $query->where('age','>=', $keyword_age)->get();
          $message = $keyword_age. "歳以上の検索が完了しました";
        }
        elseif(empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 2){
          $users = $query->where('age','<=', $keyword_age)->get();
          $message = $keyword_age. "歳以下の検索が完了しました";
        }
        elseif(!empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 1){
          $users = $query->where('name','like', '%' .$keyword_name. '%')->where('age','>=', $keyword_age)->get();
          $message = "「".$keyword_name . "」を含む名前と". $keyword_age. "歳以上の検索が完了しました";
        }
        elseif(!empty($keyword_name) && !empty($keyword_age) && $keyword_age_condition == 2){
          $users = $query->where('name','like', '%' .$keyword_name. '%')->where('age','<=', $keyword_age)->get();
          $message = "「".$keyword_name . "」を含む名前と". $keyword_age. "歳以下の検索が完了しました";
        }
        elseif(empty($keyword_name) && empty($keyword_age) && $keyword_sex == 1){
          $users = $query->where('sex','男')->get();
          $message = "男性の検索が完了しました";
        }
        elseif(empty($keyword_name) && empty($keyword_age) && $keyword_sex == 2){
          $users = $query->where('sex','女')->get();
          $message = "女性の検索が完了しました";
        }
        else {
          $users = null;
          $message = "検索結果はありません。";
        }

        return  [$users,$message];
}

}

#コントローラーを編集

app/Http/Controllers/UsersController.php
class UsersController extends Controller
{
    //
    public function index() {
      $users = User::all();
      return view('index')->with('users', $users);
    }

    public function serch(Request $request) {
      $keyword_name = $request->name;
      $keyword_age = $request->age;
      $keyword_sex = $request->sex;
      $keyword_age_condition = $request->age_condition;

      list($users,$message) = Serch::serch($keyword_name,$keyword_age,$keyword_sex,$keyword_age_condition);

      return view('/serch')->with([
        'users' => $users,
        'message' => $message,
      ]);

}
}

#サービスプロパイダーとエイリアスの登録

config/app.php
'providers' => [
    App\Providers\SerchServiceProvider::class,



    'aliases' => [
        'Serch' => App\Facades\Serch::class,

.
.


#終了です。

31
32
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
31
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?