Yohei Umezu
Yohei Umezu

Reputation: 431

laravel: I cannot complete search form

I am building a search form for posts table.

Now I can search description, but when I select a category or date, and search, the result page shows all the posts. Which means search functionality for 'category' and 'date' don't work.

I don't want to build a strict search functionality, so I used orWhere query clause.

web.php

Route::get('results', 'ResultsController@index')->name('posts.result');

ResultsController.php

public function index(Request $request)
{
    $keyword = $request->get('keyword');
    $category = $request->get('category_id');
    $date = $request->get('date');

    if ($keyword || $category || $date) {
        $posts = Post::Where('keyword', 'LIKE', '%' . $keyword . '%')
            ->orWhere('category_id', $category)
            ->orWhere('date', $date)
            ->paginate(10);
        return view('posts.result', compact('posts'));
    } else {
        $posts = Post::latest()
            ->orderBy('date', 'asc')
            ->paginate(10);
        return view('posts.result', compact('posts'));
    }
}

posts table migration

Schema::create('posts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('image');
    $table->unsignedBigInteger('category_id');
    $table->string('title');
    $table->string('place');
    $table->string('map');
    $table->date('date');
    $table->string('organizer');
    $table->string('organizer_link');
    $table->timestamp('published_at')->nullable();
    $table->text('description');
    $table->timestamps();
});

result.blade.php

<form action="{{ route('posts.result') }}" class="search" method="GET">
    <input type="text" name="description" class="search_text" placeholder="Enter the key words">
    <select name="category" id="select" class="Genre">
        <option value="" hidden name="category">Category</option>
        @foreach(App\Category::all() as $category)
        <option value="{{$category->id}}">{{$category->name}}</option>
        @endforeach
    </select>
    <input type="text" name="date" class="search_date" id="date" placeholder="Choose date">
    <button type="submit" class="test">
        <i class="fas fa-search "></i>
    </button>
    </div>
</form>

Upvotes: 0

Views: 78

Answers (1)

Raul
Raul

Reputation: 579

I tried to adjust your code to only include the search params that are actually passed. However, could not test it as i have to leave, so please test if this works. The code should work with any of those passed independently, which is why i had to do the search array and the match key in there.

public function index(Request $request)
{
    $keyword = $request->get('keyword');
    $category_id = $request->get('category_id');
    $date = $request->get('date');

    if ($keyword || $category_id || $date) {
        $search = [];
        if (!empty($keyword)) {
            $search[] = [
                'column' => 'keyword',
                'value' => "%{$keyword}%",
                'match' => 'LIKE',
            ];
        }

        if (!empty($category_id)) {
            $search[] = [
                'column' => 'category_id',
                'value' => $category_id,
                'match' => '=',
            ];
        }

        if (!empty($date)) {
            $search[] = [
                'column' => 'date',
                'value' => $date,
                'match' => '=',
            ];
        }

        // by here, we have for sure 1 condition
        $posts = Post::where($search[0]['column'], $search[0]['match'], $search[0]['value']);

        if (count($search) > 1) {
            // multiple conditions, using orWhere
            array_shift($search);
            foreach ($search as $condition) {
                $posts->orWhere($condition['column'], $condition['match'], $condition['value']);
            }
        }

        $posts = $posts->paginate(10);
    } else {
        $posts = Post::latest()
            ->orderBy('date', 'asc')
            ->paginate(10);
    }

    return view('posts.result', compact('posts'));
}

Your form:

<form action="{{ route('posts.result') }}" class="search" method="GET">
    <input type="text" name="keyword" class="search_text" placeholder="Enter the key words">
    <select name="category_id" id="select" class="Genre">
        <option value="" hidden>Category</option>
        @foreach(App\Category::all() as $category)
        <option value="{{$category->id}}">{{$category->name}}</option>
        @endforeach
    </select>
    <input type="text" name="date" class="search_date" id="date" placeholder="Choose date">
    <button type="submit" class="test">
        <i class="fas fa-search "></i>
    </button>
    </div>
</form>

Upvotes: 2

Related Questions