tanmaymishu / laravel-funnel
将 HTTP 查询字符串参数绑定到 Eloquent 模型属性。
Requires
- php: >=7.2
Requires (Dev)
- orchestra/testbench: ^4.0
- phpunit/phpunit: ^8.5
This package is auto-updated.
Last update: 2024-09-08 21:53:13 UTC
README
基于 HTTP 查询字符串参数(如 ?key=value)进行结果过滤是日常网络开发中常见的任务之一。
Laravel Funnel 尝试减轻应用和维护过滤器时的认知负担。
特性
- 参数属性绑定:将查询字符串 参数 绑定到 Eloquent 模型 属性。
- 代码生成:通过简单的命令生成过滤器类。
- 多值参数:通过允许 URL 中的逗号分隔列表,使多值参数变得容易处理。例如:
http://example.com/posts?title=foo,bar。 - 排序:使用简单的
--clause=orderBy参数创建“排序感知”过滤器。 - 搜索:使用简单的
--operator=like参数创建“搜索感知”过滤器。 - 关联模型属性绑定:使用
relation.attribute格式(如--attribute=comments.body)轻松绑定关联模型的属性。 - 预加载:Funnel 默认支持预加载。将关系传递到默认的
?with查询参数。例如:http://example.com/posts?with=comments,categories。 - 自定义:生成的过滤器类中的查询逻辑可以根据您的需求进行覆盖。
安装
使用包管理器 composer 安装 laravel-funnel。
composer require tanmaymishu/laravel-funnel
使用方法
快速入门
假设您有一个 Post 模型和一个属性 published,您想过滤所有已发布的帖子。URL 表示可能如下所示
http://example.com/posts?published=1
步骤 1: 运行 php artisan funnel:filter Published。在 app/Filters 目录中创建一个新的 Published 类,并假设以下配置
- 您有一个名为
published的属性 - 您有一个名为
published的查询字符串标识符 - 您想要的查询子句是
WHERE WHERE子句的运算符是=
不用担心,所有这些“默认假设”都可以被覆盖(参见下方的 CLI 选项)。
步骤 2: 打开您想要使用此过滤器的模型(例如 Post.php)。在您的类中添加以下两行
use HasFilters; protected $filters = [];
然后,将过滤器类添加到 $filters 数组中。例如
<?php namespace App; use Illuminate\Database\Eloquent\Model; use TanmayMishu\LaravelFunnel\HasFilters; class Post extends Model { use HasFilters; protected $filters = [ \App\Filters\Published::class, ]; }
步骤 3: 现在,您可以通过调用 Post::filtered() 来获取过滤后的帖子。它返回一个 Builder 实例,允许您进一步链式查询,例如:Post::filtered()->with('comments')->get()。您必须像通常一样添加 ->get(),以将结果作为集合返回。
您可以在 $filters 数组中添加任意多的过滤器。在您的查询字符串中添加参数:?title=foo&published=1,Funnel 将为您选择合适的过滤器。
CLI 选项
- 此包包含一个
funnel:filter命令。以下命令将显示所有详细信息,包括它接受的参数和选项。php artisan -h funnel:filter
Create a new filter Usage: funnel:filter [options] [--] <name> Arguments: name The name of the filter class. Options: -a, --attribute[=ATTRIBUTE] The attribute name of the model (e.g. is_active). Default: Snake cased filter_class -p, --parameter[=PARAMETER] The name of the request query parameter (e.g. active). Default: Snake cased filter_class -o, --operator[=OPERATOR] The operator for the WHERE clause (e.g. >, like, =, <). Default: = -c, --clause[=CLAUSE] The clause for the query (e.g. where, orderBy, groupBy). Default: where funnel:filter命令接受 1 个 参数(过滤器类的名称)和 4 个 选项(有时也称为 标志)。--attribute=(简称:-a):模型的属性。如果没有提供此选项,则默认的 attribute 将是作为 argument 提供的过滤器类名称的 snake_case 形式。--parameter=(简称:-p):将从 URL 接收的查询字符串参数。如果没有提供此选项,则默认的 parameter 将是作为 argument 提供的过滤器类名称的 snake_case 形式。--operator=(简称:-o):用于WHERE子句的运算符。如果没有提供此选项,则默认使用=运算符。--clause=(简称:-c):用于查询的子句。如果WHERE子句不满足您的需求,您可以指定不同的子句(目前支持:orderBy,groupBy)
注意
- 如果运算符是
like,则参数值将在其两侧分别包围着%通配符。这种行为可能在将来进行自定义。 - 如果子句是
orderBy,则期望以下两个参数值之一:a) asc b) desc
示例
让我们看看一些漏斗命令以及它们根据 URL 生成的结果
模型和关系考虑事项
// A Post hasMany Comments and a Comment hasMany Replies // Post is the model that we want to query. Post::createMany([ ['title' => 'Foo', 'body' => 'Lorem ipsum'], // We'll call it Post 1 ['title' => 'Bar', 'body' => 'Dolor sit amet'], // We'll call it Post 2 ]); Comment::createMany([ ['body' => 'Comment A', 'post_id' => 1], ['body' => 'Comment B', 'post_id' => 2], ]); Reply::createMany([ ['content' => 'Reply A', 'comment_id' => 1], ['content' => 'Reply B', 'comment_id' => 2], ]);
[注意:以下示例使用了长选项和短选项的混合。请随意使用您喜欢的任何形式。]
多值参数([] 语法)
- 漏斗可以理解多值查询字符串参数:
http://example.com/posts?title[]=foo&title[]=bar。您无需为此执行任何额外步骤。 - 如您所见,您需要在每个查询参数后附加数组表示法
[]。 - 漏斗将通过
OR子查询传递参数值(foo & bar)。 - 像
http://example.com/posts?title[]=foo&title[]=bar这样的 GET 请求将指示我们获取所有标题为 foo 或 bar 的帖子。
多值参数(, 语法)
- 除了
[]语法之外,漏斗还提供了一种更简单的、替代的逗号 (,) 语法用于多值参数:http://example.com/posts?title=foo,bar - 与
[]语法相比,,语法的好处是您不需要为每个参数重复param[]。
绑定相关模型的属性
- 属性不必位于正在查询的模型中。如果您处于想要过滤所有带有评论体 "Foo" 的帖子的状态,假设您的 Post 模型有一个
comments()关系,您应该传递--attribute=comments.body选项- 示例命令:
php artisan funnel:filter Comment --attribute=comments.body。即使body属性位于Comment模型而不是Post模型,漏斗也会过滤出指定评论体的所有帖子。 - 示例 URL:
http://example.com/posts?comment=Foo
- 示例命令:
- 甚至可以将嵌套相关模型的属性绑定到参数。如果我们想获取所有评论中回复体为
Bar的帖子,只要存在这些关系,我们也可以做到这一点- 示例命令:
php artisan funnel:filter Reply --attribute=comments.replies.body - 示例 URL:
http://example.com/posts?reply=Bar
- 示例命令:
预加载
- 漏斗自带预加载支持。将您的关系到默认的
?with查询参数。例如:http://example.com/posts?with=comments,categories。 - 如果您需要自定义默认为
with的 eager 关键字名称,您可以在config/funnel.php文件中完成。在这样做之前,您需要运行以下命令以发布您的配置文件:php artisan vendor:publish --provider="TanmayMishu\LaravelFunnel\FunnelServiceProvider"
自定义
- 如果生成的过滤器类的
apply()方法不符合您的需求,您始终可以实现自己的apply()方法,但它应该与父类的签名匹配。
贡献
欢迎提交拉取请求。对于重大更改,请先创建一个问题来讨论您想要进行更改的内容。
请确保根据需要更新测试。