如何使用 Eloquent 实现包含搜索
How to implement search with contains using Eloquent
我使用 Eloquent 创建搜索查询,如下所示:
User::where('firstName', 'like', '%' . $search_value . '%')
->orWhere('lastName', 'like', '%' . $search_value . '%')
->get();
这是工作。但我需要用包含搜索。例如,如果我的搜索值为 hello world
,我应该找到值为 World! Okay, hello
的行。
我该怎么做?
1) 您可以使用范围方法创建搜索特征。
App\Traits\Searchable.php:
namespace App\Traits;
trait Searchable
{
public function scopeSearch($builder, $query, $columns = null)
{
if($query){
$words = explode(' ', $query);
$words = array_filter($words);
if(!$columns){
$columns = $this->searchable;
}
$builder->where(function ($builder) use ($words, $columns) {
foreach ($words as $word) {
$builder->where(function ($builder) use ($word, $columns) {
foreach ($columns as $column) {
if (strpos($column, '.') !== false) {
[$relation, $column] = explode('.', $column);
$builder->orWhereHas($relation, function ($query) use ($column, $word) {
$query->where($column, 'like', '%' . $word . '%');
});
} else {
$builder->oRwhere($this->getTable() . '.' . $column, 'like', '%' . $word . '%');
}
}
});
}
});
}
}
}
2) 添加 Searchable
特征到模型和 $searchable
属性 具有可搜索列。
App\Model\User.php:
class User extends Authenticatable
{
use Searchable;
public $searchable = ['firstName', 'lastName'];
3) 使用搜索范围:
$users = User::search($search_value)->get();
或特定列:
$users = User::search($search_value, ['firstName', 'lastName', 'role.title'])->get();
现在您可以将此特征用于所有模型并通过模型列和模型关系列进行搜索。
第一个参数接受查询,第二个参数接受列或带点的关系列 (relation.column
)。
我们将查询拆分为单词并搜索不同列中的所有单词匹配项。
所以最简单的方法是使用 Eloquent 宏:
use Illuminate\Database\Eloquent\Builder;
// ...
Builder::macro('whereLike', function(string $attribute, string $searchTerm) {
return $this->orWhere($attribute, 'LIKE', "%{$searchTerm}%");
});
现在您可以像这样搜索模特:
User::query()
->whereLike('name', $searchTerm)
->whereLike('email', $searchTerm)
->get();
有关以下主题的更多信息:https://freek.dev/1182-searching-models-using-a-where-like-query-in-laravel
和
https://tighten.co/blog/the-magic-of-laravel-macros
我使用 Eloquent 创建搜索查询,如下所示:
User::where('firstName', 'like', '%' . $search_value . '%')
->orWhere('lastName', 'like', '%' . $search_value . '%')
->get();
这是工作。但我需要用包含搜索。例如,如果我的搜索值为 hello world
,我应该找到值为 World! Okay, hello
的行。
我该怎么做?
1) 您可以使用范围方法创建搜索特征。
App\Traits\Searchable.php:
namespace App\Traits;
trait Searchable
{
public function scopeSearch($builder, $query, $columns = null)
{
if($query){
$words = explode(' ', $query);
$words = array_filter($words);
if(!$columns){
$columns = $this->searchable;
}
$builder->where(function ($builder) use ($words, $columns) {
foreach ($words as $word) {
$builder->where(function ($builder) use ($word, $columns) {
foreach ($columns as $column) {
if (strpos($column, '.') !== false) {
[$relation, $column] = explode('.', $column);
$builder->orWhereHas($relation, function ($query) use ($column, $word) {
$query->where($column, 'like', '%' . $word . '%');
});
} else {
$builder->oRwhere($this->getTable() . '.' . $column, 'like', '%' . $word . '%');
}
}
});
}
});
}
}
}
2) 添加 Searchable
特征到模型和 $searchable
属性 具有可搜索列。
App\Model\User.php:
class User extends Authenticatable
{
use Searchable;
public $searchable = ['firstName', 'lastName'];
3) 使用搜索范围:
$users = User::search($search_value)->get();
或特定列:
$users = User::search($search_value, ['firstName', 'lastName', 'role.title'])->get();
现在您可以将此特征用于所有模型并通过模型列和模型关系列进行搜索。
第一个参数接受查询,第二个参数接受列或带点的关系列 (relation.column
)。
我们将查询拆分为单词并搜索不同列中的所有单词匹配项。
所以最简单的方法是使用 Eloquent 宏:
use Illuminate\Database\Eloquent\Builder;
// ...
Builder::macro('whereLike', function(string $attribute, string $searchTerm) {
return $this->orWhere($attribute, 'LIKE', "%{$searchTerm}%");
});
现在您可以像这样搜索模特:
User::query()
->whereLike('name', $searchTerm)
->whereLike('email', $searchTerm)
->get();
有关以下主题的更多信息:https://freek.dev/1182-searching-models-using-a-where-like-query-in-laravel 和 https://tighten.co/blog/the-magic-of-laravel-macros