Laravel多参数(关键词+地点+部门)搜索功能实现故障求助
问题根因
- 筛选逻辑错误:集合filter回调中使用
Post::where('standort_name') == $location这类写法完全错误,Post::where()会启动新的查询构造器返回查询对象,而非判断当前遍历的$post属性值,永远无法匹配正确结果 - 逻辑运算符错误:原有代码用
||(或)做判断,但需求是同时满足所有筛选条件,应该用&&(且)逻辑 - 字段名不匹配:Post模型fillable中存储地点的字段是
standort,不是代码中写的standort_name - 性能问题:先全量查询所有帖子再在内存过滤,数据量大时性能极差,应该直接用数据库查询构造器做筛选
- 下拉默认值问题:原有下拉默认选项是disabled状态,用户不选择该字段时提交不会携带对应参数,会导致条件判断异常,还缺少选中后回填的逻辑
- Standort模型fillable字段配置错误:当前写的是
abteilung_name,应该改为standort_name
修复后的代码
控制器代码
public function index(Request $request) { // 初始化查询构造器,不提前执行查询 $postsQuery = Post::orderBy('titel'); $standorts = Standort::orderBy('standort_name')->get(); $abteilungs = Abteilung::orderBy('abteilung_name')->get(); // 关键词筛选 if ($request->filled('s')) { $word = strtolower($request->get('s')); $postsQuery->whereRaw('LOWER(titel) LIKE ?', ["%{$word}%"]); } // 地点筛选 if ($request->filled('standort')) { $postsQuery->where('standort', $request->standort); } // 部门筛选 if ($request->filled('abteilung')) { $postsQuery->where('abteilung_name', $request->abteilung); } // 最后执行查询获取结果 $posts = $postsQuery->get(); return view('posts.overview', [ 'posts' => $posts, 'standorts' => $standorts, 'abteilungs' => $abteilungs, ]); }
Blade模板代码(补全默认空选项和回填逻辑)
<form class="mb-5 flex justify-left grid grid-cols-4 gap-x-20" action="{{ route('overview') }}" method="get"> <div class="w-full h-12 text-left col-start-1 col-end-1"> <input placeholder="Schlagwort" type="text" id="s" name="s" value="{{ request()->get('s') }}" class="mb-2 w-full h-full bg-white bg-opacity-95 rounded focus:ring-2 border border-gray-300 focus:border-indigo-500 text-base outline-none text-gray-700 text-xl py-1 px-3 leading-8"> </div> <div class="text-left mb-4 h-12"> <select name="abteilung" id="abteilung" class="h-full w-full flex justify-center bg-white bg-opacity-95 rounded focus:ring-2 border border-gray-300 focus:border-indigo-500 text-base outline-none text-gray-700 text-lg text-center leading-8"> <option value="">Abteilung</option> @foreach($abteilungs as $abteilung) <option value="{{ $abteilung->abteilung_name }}" {{ request('abteilung') == $abteilung->abteilung_name ? 'selected' : '' }}>{{ $abteilung->abteilung_name }}</option> @endforeach </select> </div> <div class="text-left mb-4 h-12"> <select name="standort" id="standort" class="h-full w-full flex justify-center bg-white bg-opacity-95 rounded focus:ring-2 border border-gray-300 focus:border-indigo-500 text-base outline-none text-gray-700 text-lg text-center leading-8"> <option value="">Standort</option> @foreach($standorts as $standort) <option value="{{ $standort->standort_name }}" {{ request('standort') == $standort->standort_name ? 'selected' : '' }}>{{ $standort->standort_name }}</option> @endforeach </select> </div> <button class="col-start-4 col-end-4 w-11/12 h-12 text-white text-2xl px-4 py-2 rounded text-base font-medium bg-gradient-to-r from-green-400 to-blue-500 float-right shadow transition duration-500 ease-in-out transform hover:-translate-y-1 hover:scale-100"> Suchen </button> </form>
可选:集合过滤写法(不推荐,仅小数据量场景使用)
如果要保留原有集合过滤的实现方式,filter回调修改为如下即可:
$posts = $posts->filter(function ($post) use ($dep, $word, $location) { $pass = true; if ($word) { $pass = $pass && Str::contains(strtolower($post->titel), $word); } if ($location) { $pass = $pass && $post->standort == $location; } if ($dep) { $pass = $pass && $post->abteilung_name == $dep; } return $pass; });
内容的提问来源于stack exchange,提问作者Frevelman
相关产品推荐
相关产品推荐

