简体   繁体   中英

How can I do a multiple search based on single fields in my web

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.

Edit

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM