tanmaymishu/laravel-funnel

将 HTTP 查询字符串参数绑定到 Eloquent 模型属性。

v0.2.1 2021-04-08 14:33 UTC

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 个 选项(有时也称为 标志)。
    1. --attribute=(简称:-a):模型的属性。如果没有提供此选项,则默认的 attribute 将是作为 argument 提供的过滤器类名称的 snake_case 形式。
    2. --parameter=(简称:-p):将从 URL 接收的查询字符串参数。如果没有提供此选项,则默认的 parameter 将是作为 argument 提供的过滤器类名称的 snake_case 形式。
    3. --operator=(简称:-o):用于 WHERE 子句的运算符。如果没有提供此选项,则默认使用 = 运算符。
    4. --clause=(简称:-c):用于查询的子句。如果 WHERE 子句不满足您的需求,您可以指定不同的子句(目前支持:orderBygroupBy

注意

  • 如果运算符是 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 请求将指示我们获取所有标题为 foobar 的帖子。

多值参数(, 语法)

  • 除了 [] 语法之外,漏斗还提供了一种更简单的、替代的逗号 (,) 语法用于多值参数: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() 方法,但它应该与父类的签名匹配。

贡献

欢迎提交拉取请求。对于重大更改,请先创建一个问题来讨论您想要进行更改的内容。

请确保根据需要更新测试。

许可

MIT