I'm building a website with Laravel and I want to create a search like a form where a user can search movies using different genres. The problem is when I try to use more than 1 genre it only displays the last option selected for each of my fields. For example, my search options are genre and year and I try to input comedy, romance, action, 1992, 2005 but only outputs action movies in 2005.
All the data is stored in a MySQL database and I used a basic to do the input with checkboxes, the data appears in the URL and does the search but only works for one of the options on each field.
<form action="/home" method="GET">
<hr>
<h4>Genre</h4><br>
@foreach($movies as $movie)
<input type="checkbox" name="genre" value="{{$movie->genre}}">{{$movie->genre}}<br>
@endforeach
<hr>
<h4>Year</h4>
@foreach($movies as $movie)
<input type="checkbox" name="year" value="{{$movie->year}}">{{$movie->year}}<br>
@endforeach
<input type="submit" class="btn btn-success" value="Search"><br>
</form>
The idea is that if a user inputs comedy, romance, action, 1992, 2005 the output show comedy movies, action movies and romance movies in 1992 and 2005.
Here is my controller where I do the search and a pagination.
public function index(Request $request)
{
$movies = \DB::table('movies');
$queries = [];
$columns = [
'genre','year'
];
foreach ($columns as $column) {
if (request()->has($column)) {
$movies = $movies->where($column, request($column));
$queries[$column] = request($column);
}
}
$movies = $movies->orderBy('created_at', 'desc')->paginate(20)->appends($queries);
return view('home', compact('movies'));
}
If you're allowing a user to select multiple genre
and year
values, your inputs needs to be arrays. Change the name
attribute to use []
:
@foreach($movies as $movie)
<input type="checkbox" name="genre[]" value="{{ $movie->genre }}">{{ $movie->genre }}<br/>
@endforeach
...
@foreach($movies as $movie)
<input type="checkbox" name="year[]" value="{{ $movie->year }}">{{ $movie->year }}<br/>
@endforeach
Since you're omitting the []
, only the last selected checkbox with the same name
is being sent to the server. With this, on the backend, your values should be arrays:
$selectedGenres = $request->input("genre");
// ["comedy", "romance", ...];
$selectedYears = $request->input("year");
// ["1990", "2019", ...];
You can then use this in a simple query:
$foundMovies = Movie::whereIn("genre", $selectedGenres)
->whereIn("year", $selectedYears)
->get();
You will likely have to ignore searching if no genre
or year
values are selected, but that can be done either via validation:
"genre" => "required|array|min:1",
"year" => "required|array|min:1"
or a check:
if(count($selectedGenres) != 0){ ... }
since your loop generates checkboxes, your "name" attribute must be an array:
@foreach($movies as $movie)
<input type="checkbox" name="genre[]" value="{{ $movie->genre }}">{{ $movie->genre }}<br/>
@endforeach
you should also add a validation rule to the formRequest just to check if the values received exists and are arrays.
"genre" => "required|array",
"year" => "required|array"
finally, your query will look like this:
$genres = $request->genre;
$years = $request->year;
Movie::when(count($genres) > 0,function ($query, $genres) {
return $query->whereIn('genre', $genres);
})
->when(count($years) > 0,function ($query, $years) {
return $query->whereIn('year', $years);
})
->get();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.