ahmedabdo / searchable
为 Laravel 模型添加搜索功能的包
README
Laravel Searchable 是一个包,它为 Laravel Eloquent 模型添加了简单可定制的搜索和筛选功能
安装
composer require ahmedabdo/searchable
搜索
搜索使用示例
- 在您的模型中使用 Abdo\Searchable\Searchable 特性。
- 在 searchable 数组中定义您要用于搜索的列。
- 利用搜索作用域在所选列上执行搜索。
// model use Abdo\Searchable\Searchable; use Abdo\Searchable\Attributes\SearchAdd; use Abdo\Searchable\Attributes\SearchColumns; class User extends Authenticatable { use Searchable; #[SearchColumns] public $searchable = [ "columns" => [ "name", "email", "role.name", "created_at" ], "eager" => [ "role" ] ]; #[SearchAdd("created_at")] public function searchByCreatedAtDayName(Builder $q, string $searchWord) { $q->orWhereRaw("DAYNAME(created_at) like ?", ["%" . $searchWord . "%"]); } } // usage User::search($searchWord)->get();
搜索列
要定义模型的搜索列,您可以使用带有 #[SearchColumns]
属性的属性装饰。此属性将包含搜索模型的默认列以及需要预加载的任何关系。如果没有设置 #[SearchColumns]
属性,则将使用可填充列作为后备。
#[SearchColumns] public $searchable = [ "columns" => [ "colame", "relation.colname", "relation.relation.colname", ], "eager" => [ "relation" ] ];
自定义搜索
如果您想为特定列自定义搜索查询,您可以创建一个带有 #[Search("colname")]
属性的方法,并针对该选择的列构建自定义查询。
#[SearchColumns] public $searchable = [ "columns" => [ "time", // stored as Y-m-d H:i:s ] ]; #[Search("time")] public function searchTime(Builder $q, string $searchWord) { $q->orWhere("time", "like", "%" . $searchWord . "%") ->orWhereRaw("DAYNAME(time) like ?", ["%" . $searchWord . "%"]); }
在上面的示例中,"time" 列在数据库中以日期时间值存储。如果您想通过天名来定制该列的搜索功能,并添加一个新的或 where 语句进行搜索,您可以使用 #[SearchAdd("colname")]
属性。
通过使用此属性,您可以将所需的或 where 语句纳入列搜索查询中,同时利用由包提供的现有搜索查询。
注意
您可以使用任意数量的 searchAdd 方法。
#[SearchAdd("time")] public function searchTimeByDayName(Builder $q, string $searchWord) { $q->orWhereRaw("DAYNAME(time) like ?", ["%" . $searchWord . "%"]); }
如果您已使用 #[Search("colname")]
或 #[SearchAdd("colname")]
自定义关系搜索,则传递给自定义方法的构建器实例将是关系模型的构建器。
public $searchable = [ "columns" => [ "patient.name", ] ]; #[Search("patient.name")]// or #[SearchAdd("patient.name")] public function searchPatientName(Builder $q, string $searchWord) { // $q is builder instance for Patient model $q->orWhere("name", "like", "%" . $searchWord . "%"); }
覆盖默认列
如果您想覆盖模型中定义的列,则可以将列作为第二个参数传递给搜索作用域。
User::search($searchWord, ["fname", "lname"])->get();
搜索选项
可以为列添加一个选项数组
#[SearchColumns] public $searchable = [ "columns" => [ "name" => ["operator" => "="] ] ]; User::search($searchWord,[ "name" => ["operator" => "=", "useCustom" => false, "useAddCondition" => false] ])
列可以有三种选项
筛选
筛选使用示例
// model use Abdo\Searchable\Searchable; class User extends Authenticatable { use Searchable; #[SearchColumns] public $searchable = [ "columns" => [ "name", "email", "role.name", "created_at" ], "eager" => [ "role" ] ]; } //request query string : // ?name=ahmed&email=startsWith|ahmed&role:name=admin&created_at=from|2020-01-01 // usage User::filter()->get();
筛选列
默认情况下,用于筛选的列将是定义在具有 #[SearchColumns]
属性的属性中的列,结合在可填充数组中指定的列。如果您想将不同的列用作筛选的默认值,则可以定义一个具有 #[FilterColumns]
属性的属性。
#[FilterColumns] public $filterable = [ "name","email", //... ];
筛选查询字符串
查询字符串参数名称应与列名称匹配。如果您正在筛选关系,则可以使用冒号 :
作为关系名称和列名称之间的分隔符,而不是点 .
查询字符串应遵循此模式。
// ?<colname>=<operator, default:"=">|<value> User::filter()->get();
如果您已使用与列名称不同的参数名称,则可以将列名称和筛选值传递给筛选作用域。
// ?<not-colname>=<operator, default:"=">|<value> // To retrieve the filter value from the query string, you can utilize the "filterParam" helper User::filter(["column_name" => filterParam("not_column_name")])->get(); // Note that if the rest of the query string parameter names match the column names // you can employ a similar approach. User::filter(["column_name" => filterParam("not_column_name")])->filter()->get();
运算符
允许用于筛选的运算符包括可以发送到 where
构建器方法的所有运算符,以及额外的运算符。
注意
在使用“between”运算符时,必须提供两个参数,用逗号分隔。如果未指定from
参数,则数据将过滤从负无穷大到to
参数。同样,如果未提供to
参数,则数据将过滤到正无穷大。例如:?created_at=bt|,2010-01-01检索所有在2010年1月1日之前创建的记录。另一个例子:?created_at=bt|2010-01-01,检索所有在2010年1月1日之后创建的记录。
筛选模式
有两种过滤模式:and
模式和or
模式,默认模式是and
。
更改模式的方法
// using or mode User::filter(mode: Mode::OR)->get(); // using and mode User::filter(mode: Mode::AND)->get(); User::filter()->get();
筛选 Blade 脚本
如果您在前端使用常规Blade模板,有一个简单的JavaScript脚本可用于简化创建过滤器表单。要包含此脚本,将@searchableScripts
指令添加到主布局中。
然后您可以按照以下步骤创建过滤器表单
用法
- 确保表单有
filter
类 - 输入名称应与相应的列名称匹配
- 对于关系,使用冒号
:
作为分隔符,例如:relation:columnName
- 在
data-filter
属性中设置所需的过滤运算符,默认为=
- 使用
filterValue("queryParam")
获取过滤值
<!-- give the form class 'filter' --> <form action="" class="filter"> <label for="">Age</label> <!-- place the filter operator in 'data-filter' attribute --> <!-- filterValue helper for getting the current filter value --> <input data-filter=">" type="number" value="{{filterValue('age')}}" name="age" id=""> <label for="">Created At From</label> <!-- for bte, bt, betweenEqual, between operators --> <!-- ex: from input with name created_at[0] to input with name created_at[1] --> <input data-filter="bt" type="date" value="{{filterValue('created_at', asArray: true)[0] ?? now()->format('Y-m-d')}}" name="created_at[0]" id=""> <label for="">Created At To</label> <input type="date" value="{{filterValue('created_at', asArray: true)[1] ?? now()->format('Y-m-d')}}" name="created_at[1]" id=""> <!-- ex: for multi value --> <label for="">Role</label> <select data-filter="in" name="role_id[]" id="" multiple> <option value="0">admin</option> <option value="1">manager</option> <option value="2">employee</option> </select> <button type="submit" >filter</button> </form>
筛选助手
filterParam
"filterParam"辅助函数用于从查询字符串中提取过滤值。当使用Blade过滤器表单时,应使用此辅助函数,尤其是如果输入字段名称与对应列名称不同。
//model #[SearchColumns] public $searchable = [ "columns" => [ "name" ], ]; //blade <form action="" class="filter"> <input data-filter="contains" type="text" value="{{filterValue('empName')}}" name="empName" id=""> </form> //usage User::filter(["name" => filterParam("empName")])->get();
filterValue
"filterValue"辅助函数用于检索用于过滤的值,以便在输入字段中显示此值,作为一个示例。
//?name=cont|ahmed&role_id=in|2,3,4 filterValue("name") // ouptut ahmed filterValue("role_id") // output 2,3,4 filterValue("role_id", true) //output [2,3,4]
自定义运算符
如果您需要定义用于过滤和搜索的自定义运算符,有两种不同的方法。
注意
自定义运算符必须以sp_
开头
在配置中
要发布配置文件,请执行以下命令
php artisan vendor:publish --provider="Abdo\Searchable\ServiceProvider"
配置文件发布后,您可以在operators
数组中定义自己的自定义运算符。
"operators" => [ "sp_is_null" => function (Builder $builder, string $column, string $word) { return $builder->whereIsNull($column)->orWhere($column, 0); }, ],
在服务提供者中
此外,您还可以在某个服务提供者的boot方法中注册自定义运算符。
ColumnConfigraution::registerOperator("sp_is_null", function (Builder $builder, string $column, string $word) { return $builder->whereIsNull($column)->orWhere($column, 0); }); //after defining your custom operator you can use them like this //?status=sp_is_null|