21
25

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 5 years have passed since last update.

Laravel 5.5 検索機能を実装してみた

Posted at

この記事では
Laravelでリレーション関係にあるテーブルのカラムから検索ができるようになります!
開発環境は、Laravel5.5 PHP MySQLです。

では早速コードを書いていきましょう!!!
まずは以下2つのマイグレーションファイルを実行し、
recipesテーブルとingredientsテーブルを作成する。

_create_recipes_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateRecipesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('recipes', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned()->index();
            $table->string('name');
            $table->timestamps();
            
            // 外部キー制約
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('recipes');
    }
}
_create_ingredients_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateIngredientsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ingredients', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('recipe_id')->unsigned()->index();
            $table->string('ingredient', 255);
            $table->timestamps();
            
            // 外部キー制約
            $table->foreign('recipe_id')->references('id')->on('recipes')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('ingredients');
    }
}

次にRecipeモデルとIngredientモデルを作成し、一対多のリレーション関係を作る。
(今回Userモデルについては割愛します。)

Recipe.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Recipe extends Model
{
    protected $fillable = ['user_id', 'name'];
    
    public function user()
    {
        return $this->belongsTo(User::class);
    }
    
    public function ingredients()
    {
        return $this->hasMany(Ingredient::class);
    }
}
Ingredient.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Ingredient extends Model
{
    protected $fillable = ['recipe_id', 'ingredient'];
    
    public function recipe()
    {
        return $this->belongsTo(Recipe::class);
    }
}

検索フォームへのルーティングを付け加えます。

/routes/web.php
//検索機能
Route::get('paginate', 'SearchController@index')->name('search.index');

検索機能に使うコントローラーを作成し、以下のように編集します。

/Controllers/SearchController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; //付け加える

use App\Recipe;//付け加える

class SearchController extends Controller
{
    public function index(Request $request)
    {
        //キーワードを取得
        $keyword = $request->input('keyword');
        
        //もしキーワードが入力されている場合
        if(!empty($keyword))
        {   
            //料理名から検索
            $recipes = DB::table('recipes')
                    ->where('name', 'like', '%'.$keyword.'%')
                    ->paginate(4);
                    
            //リレーション関係にあるテーブルの材料名から検索
            $recipes = Recipe::whereHas('ingredients', function ($query) use ($keyword){
                $query->where('ingredient', 'like','%'.$keyword.'%');
            })->paginate(4);
            
        }else{//キーワードが入力されていない場合
            $recipes = DB::table('recipes')->paginate(4);
        }
        //検索フォームへ
        return view('search.index',[
            'recipes' => $recipes,
            'keyword' => $keyword,
            ]);
    }
}
/search/index.blade.php
   //検索フォーム
   <div class="container">
       <div class="row">
            <div class="col-md-3">   
                <form class="form-inline">
                    <div class="form-group">
                    <input type="text" name="keyword" value="{{ $keyword }}"
                    placeholder="料理名か材料名を入力">
                    <input type="submit" value="検索" >
                    </div>
                </form>
            </div>
        </div>
    </div>

    //料理名の表示
    <div class="container">
        @if(count($recipes) > 0)
          <div class="row">
            @foreach($recipes as $recipe)
            <div class="col-md-3">
              {{ $recipe->name }}
            </div>
            @endforeach
           </div>
        @endif
                //ページネーション機能
        <div class="paginate">
            {{ $recipes->render('pagination::bootstrap-4') }}
        </div>
     </div>

以上で簡単な検索機能の完成です!
検索フォームで料理名か材料名を入力するとその条件にあった料理名が表示されます!
今回はシンプルな作りですが、これに加えて写真や料理コメントなどを付け加えるといいかもしれないですね!

参考文献
https://readouble.com/laravel/5.5/ja/queries.html#pessimistic-locking
https://readouble.com/laravel/5.5/ja/eloquent-relationships.html#querying-relationship-existence
https://readouble.com/laravel/5.5/ja/pagination.html

閲覧ありがとうございました!

21
25
1

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
21
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?