Reputation: 431
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
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