jedrzej / searchable
用于Laravel Eloquent模型的搜索/过滤特性 - 使用请求参数过滤模型
Requires
Requires (Dev)
Suggests
- jedrzej/sortable: Allows sorting your models using request parameters
- jedrzej/withable: Allows eager loading of relations using request parameters
This package is auto-updated.
Last update: 2024-09-05 18:28:29 UTC
README
此包为Laravel 4/5/6的Eloquent模型添加搜索/过滤功能。
以下包可能对您也有用
- Withable - 允许使用请求参数进行关系预加载
- Sortable - 允许使用请求参数对模型进行排序
- Pimpable - 一个组合了Sortable、Searchable和Withable行为的元包
Composer安装
将以下行添加到项目中composer.json
文件中
"jedrzej/searchable": "0.0.17"
或者在项目的根目录下命令行中运行以下命令
composer require "jedrzej/searchable" "0.0.17"
设置可搜索模型
为了让Eloquent模型可搜索,将特性添加到模型中并定义一个模型可以过滤的字段列表。您可以定义一个 $searchable 属性或者实现一个 getSearchableAttributes 方法,如果想要执行一些逻辑来定义可搜索字段列表。
use Jedrzej\Searchable\SearchableTrait; class Post extends Eloquent { use SearchableTrait; // either a property holding a list of searchable fields... public $searchable = ['title', 'forum_id', 'user_id', 'created_at']; // ...or a method that returns a list of searchable fields public function getSearchableAttributes() { return ['title', 'forum_id', 'user_id', 'created_at']; } }
为了使所有字段可搜索,在可搜索字段列表中放入一个星号 *。
public $searchable = ['*'];
也可以黑名单模型属性,以防止它们被过滤。
您可以定义一个 $notSearchable 属性或实现一个 getNotSearchableAttributes 方法,如果想要执行一些逻辑来定义可搜索字段列表。
use Jedrzej\Searchable\SearchableTrait; class Post extends Eloquent { use SearchableTrait; // either a property holding a list of not searchable fields... public $notSearchable = ['created_at']; // ...or a method that returns a list of not searchable fields public function getNotSearchableAttributes() { return ['created_at']; } }
如果定义了这两个列表 - 可搜索和不可搜索的列 - 最终的可搜索字段集将包含所有白名单属性,除了所有黑名单属性。
搜索模型
SearchableTrait
为模型添加了一个 filtered()
范围 - 您可以传递一个查询数组作为过滤条件
// return all posts with forum_id equal to $forum_id Post::filtered(['forum_id' => $forum_id])->get(); // return all posts with with <operator> applied to forum_id Post::filtered(['forum_id' => <operator>])->get();
或者它将使用 Request::all()
作为默认值
// if you append ?forum_id=<operator> to the URL, you'll get all Posts with <operator> applied to forum_id Post::filtered()->get();
选择查询模式
默认查询模式是将所有查询的合取(AND
)应用于可搜索模型。可以通过将 mode
查询参数的值设置为 or
来将其更改为析取(OR
)。如果已经使用了 mode
查询参数,则将使用 getQueryMode
方法返回的名称。
构建查询
SearchableTrait
支持以下运算符
比较运算符
比较运算符允许根据模型属性与查询值的比较结果进行过滤。它们适用于字符串、数字和日期。它们的格式如下
(<operator>)<value>
以下比较运算符可用
gt
用于大于
比较运算ge
用于大于等于
比较运算lt
用于小于
比较运算,例如le
用于小于等于
比较运算
为了过滤2015年和更新的帖子,应使用以下查询
?created_at=(ge)2015-01-01
等于/在运算符
Searchable 特性允许根据属性的精确值或值集进行过滤,具体取决于传递给查询参数的值的类型。如果值包含逗号,则参数在逗号处拆分并用作 IN
过滤的数组输入,否则应用精确匹配。
为了过滤ID为42的用户帖子,应使用以下查询
?user_id=42
为了过滤ID为7或8的论坛帖子,应使用以下查询
?forum_id=7,8
类似运算符
类似操作符允许使用LIKE
查询进行筛选。如果使用精确匹配操作符,但值以%
符号作为第一个或最后一个字符时,则会触发此操作符。
为了筛选以How
开头的帖子,应使用以下查询
?title=How%
注意:
百分号字符用于对URL中的特殊字符进行编码,因此在发送请求时,请确保您使用的工具正确地将%
字符编码为%25
空操作符
(null)
空操作符允许筛选属性为空的模型。
为了筛选没有附件的帖子,应使用以下查询
?attachment_id=(null)
否定操作符
可以通过在操作符前添加!
来获取查询的否定结果。
一些示例
//filter posts from all forums except those with id 7 or 8
?forum_id=!7,8
//filter posts older than 2015
?created_at=!(ge)2015
//filter posts with attachment
?attachment_id=!(null)
单个属性的多重约束
可以为单个模型属性应用多个约束。为了实现这一点,提供查询过滤器的数组而不是单个过滤器
// filter all posts from year 20** except 2013
?created_at[]=20%&created_at[]=!2013%
按关系属性筛选
可以按模型关系的属性进行筛选——将应用Eloquent的whereHas()
。为了按关系筛选,将关系属性添加到searchable
字段列表中,形式为relation:attribute
。在查询中应使用相同的字符串来按该关系的属性进行筛选,例如
// allow filtering on user's active field
protected $searchable = ['user:active'];
// filter only posts of active users
?user:active=1
也可以通过应用Eloquent的whereDoesntHave()
来否定搜索并筛选没有匹配关系的对象。为了这样做,需要在关系名称前加上!
// allow filtering on comment's approved field
protected $searchable = ['comments:approved'];
// filter only posts that have approved comments
?comments:approved=1
// filter only posts that have not-approved comments
?comments:approved=1
// filter only posts that do not have approved comments
?!comments:approved=1
如果您想要按嵌套关系进行筛选,只需提供带有冒号代替点的嵌套关系名称即可。这是必要的,因为PHP会自动将点替换为下划线。
// filter only posts that have comments from active authors
?comments:author:active=1
覆盖默认筛选逻辑
可以处理选定的过滤器以使用自己的逻辑,例如,当筛选器名称与用于筛选的属性名称不匹配时,或者需要执行某些自定义操作。为了覆盖xyz
筛选器的逻辑,您需要在您的模型中定义一个名为processXyzFilter
的方法。如果筛选器已处理且默认逻辑不应再发生,则此方法应返回true
。
// use one filter to search in multiple columns protected function processNameFilter(Builder $builder, Constraint $constraint) { // this logic should happen for LIKE/EQUAL operators only if ($constraint->getOperator() === Constraint::OPERATOR_LIKE || $constraint->getOperator() === Constraint::OPERATOR_EQUAL) { $builder->where(function ($query) use ($constraint) { $query->where('first_name', $constraint->getOperator(), $constraint->getValue()) ->orWhere('last_name', $constraint->getOperator(), $constraint->getValue()); }); return true; } // default logic should be executed otherwise return false; }
为了覆盖关系搜索的筛选器,将筛选器名称中的冒号替换为下划线。如果您想覆盖user:active
的逻辑,您需要定义processUser_ActiveFilter
方法。