我正在寻求实现一个搜索功能,该功能可以选择包括供用户搜索的各个字段。
到目前为止我的代码:
$categories = $request->input('category'); // array(int)
$textSearch = $request->input('text'); // string
$query = Product::query();
if(!is_null($categories)){
//$query->selectSub();
foreach($categories as $catId){
$category = ShopCategory::find($catId);
$query = $query->whereBelongsTo($category);//TODO
}
}
if(!is_null($textSearch)){
$query = $query->whereAny([
'name',
'description',
'shortDescription',
],
'like', '%'.$textSearch.'%');
}
$searchResults = $query->paginate(36);
我的目标是达到相当于以下内容的 SQL 语句:
SELECT * FROM products WHERE (shop_category_id = ? OR shop_category_id = ?) AND (/* text search LIKE */)
但到目前为止,我最终得到的更多的是:
SELECT * FROM products WHERE shop_category_id = ? AND shop_category_id = ? AND (/* text search LIKE */)
其中每个类别 id 都AND
作为整体查询的一部分进行编辑,而不是OR
在组中进行编辑。
我知道or*()
查询方法,但不清楚如何正确地将它们分组以获得所需的效果,而不是仅仅OR
将它们与文本搜索一起使用。
编辑:根据已接受的答案,我得出了以下结论:
$mainQuery->where(function($query) use ($categories) {
foreach ($categories as $catId) {
$category = ShopCategory::find($catId);
$query->orWhereBelongsTo($category);
}
});
您可以通过使用
where
带有回调的函数将一些 where 条件包装到一个组中。回调内应用于构建器的任何条件都将被包裹在括号中。例如:将给出以下查询:
OR
由于第一个位置是否是 a or并不重要AND
,因此您可以将其放入循环中而不必担心第一个OR
:该查询是动态生成的,将返回以下 SQL:
由于“列条件”被包装在一个组中,因此它们不会干扰第一个条件。