mehtadsadeghi/laravel-filter-querystring

轻松根据URL查询字符串参数过滤您的查询。

v1.1.13 2024-03-18 03:39 UTC

This package is auto-updated.

Last update: 2024-09-18 04:49:07 UTC


README

轻松根据URL查询字符串参数过滤您的查询。

兼容Laravel 5.x 6.x 7.x 8.x 9.x 10.x 11.x.

目录

描述问题

你可能遇到过需要根据URL查询字符串中给定的参数过滤查询的情况。在开发逻辑后,你可能有了这样的代码:

$users = User::latest();

if(request('username')) {
    $users->where('username', request('username'));
}

if(request('age')) {
    $users->where('age', '>', request('age'));
}

if(request('email')) {
    $users->where('email', request('email'));
}

return $users->get();

这可以工作,但不是一种好的做法。

当参数数量开始增加时,这类if语句的数量也会增加,你的代码变得庞大且难以维护。

这也违反了SOLID原则中的开/闭原则,因为当你有一个新参数时,你需要进入现有的代码并添加新的逻辑(这可能会破坏现有的实现)。

因此,我们需要设计一种方法来使我们的过滤器逻辑相互独立,并将它们应用到最终的查询中,这正是这个包背后的整个想法。

使用方法

  1. 首先,你需要安装这个包

$ composer require mehradsadeghi/laravel-filter-querystring

  1. 然后,你应该在你的模型中使用FilterQueryString特性,并定义$filters属性,它可以包含可用过滤器或你的自定义过滤器
use Mehradsadeghi\FilterQueryString\FilterQueryString;

class User extends Model
{
    use FilterQueryString;

    protected $filters = [];

    ...
}
  1. 你需要在你的Eloquent查询中使用filter()方法。例如
User::select('name')->filter()->get();

可用方法

为了解释每个方法,假设我们在我们的users表中有这样的数据

假设我们的查询是这样的

User::filter()->get();

排序

排序是SQL语句中的order by的等价物,可以在FilterQueryString中灵活使用

约定

?sort=field
?sort=field,sort_type
?sort[0]=field1&sort[1]=field2
?sort[0]=field1&sort[1]=field2,sort_type
?sort[0]=field1,sort_type&sort[1]=field2,sort_type

在User.php中

protected $filters = ['sort'];

单个sort:

https://example.com?sort=created_at

输出

  • 注意:当你没有定义sort_type时,它将默认为asc

多个sort:

https://example.com?sort[0]=age,desc&sort[1]=created_at,desc

输出

请记住:无效值的sort参数将被查询忽略,并且对结果没有影响。

比较

比较由6个过滤器组成

  • greater
  • greater_or_equal
  • less
  • less_or_equal
  • between
  • not_between

约定

?greater=field,value
?greater_or_equal=field,value
?less=field,value
?less_or_equal=field,value
?between=field,value1,value2
?not_between=field,value1,value2

在User.php中

protected $filters = [
    'greater',
    'greater_or_equal',
    'less',
    'less_or_equal',
    'between',
    'not_between'
];

例如greater:

https://example.com?greater=age,20

输出

例如not_between:

https://example.com?not_between=age,21,30

输出

请记住:无效值的比较参数将被查询忽略,并且对结果没有影响。

在...中

IN子句是SQL语句中的where in的等价物。

约定

?in=field,value1,value2

在User.php中

protected $filters = ['in'];

示例:

https://example.com?in=name,mehrad,reza

输出

请记住:无效值的in参数将被查询忽略,并且对结果没有影响。

相似

LIKE子句是SQL语句中的like '%value%'的等价物。

约定

?like=field,value
?like[0]=field1,value1&like[1]=field2,value2

在User.php中

protected $filters = ['like'];

单个like:

https://example.com?like=name,meh

输出

多个like:

https://example.com?like[0]=name,meh&like[1]=username,dar

输出

请注意,如果like参数的值无效,则将从查询中忽略它,并且对结果没有影响。

Where子句(默认过滤器)

通常,当您的查询字符串参数不是之前提供的方法之一时,它将通过默认过滤器进行过滤,该默认过滤器是where SQL语句。当您需要直接过滤您表中的一列时,这是一个合适的过滤器。

约定

?field=value
?field1=value&field2=value
?field1[0]=value1&field1[1]=value2
?field1[0]=value1&field1[1]=value2&field2[0]=value1&field2[1]=value2 

假设我们想要过滤nameusernameage数据库列,在User.php中

protected $filters = ['name', 'username', 'age'];

示例:

https://example.com?name=mehrad

输出

示例:

https://example.com?age=22&username=dariush123

输出

示例:

https://example.com?name[0]=mehrad&name[1]=dariush

输出

示例:

https://example.com?name[0]=mehrad&name[1]=dariush&username[0]=mehrad123&username[1]=reza1234

输出

请注意,如果default过滤器参数的值无效,则将从查询中忽略它,并且对结果没有影响。

自定义过滤器

通过自定义过滤器,您可以定义自己的方法作为过滤器。这有助于SOLID原则的开放/封闭性,因此每次需要新的过滤器时,您不必编辑以前的过滤器,只需为它编写一个单独的方法即可。

让我们创建一个自定义过滤器。假设您想创建一个名为all_except的过滤器,该过滤器检索除指定的用户之外的所有用户

在User.php中

protected $filters = ['all_except'];

public function all_except($query, $value) {
    return $query->where('name', '!=', $value);
}

为了测试我们新添加的过滤器

https://example.com?all_except=mehrad

输出

注意,您自定义的过滤器具有最高优先级,这意味着您甚至可以覆盖现有的过滤器。

例如,让我们将in过滤器修改为仅接受3个值

在User.php中

protected $filters = ['in'];

public function in($query, $value) {
    
    $exploded = explode(',', $value);

    if(count($exploded) != 4) {
        // throwing an exception or whatever you like to do
    }

    $field = array_shift($exploded);

    return $query->whereIn($field, $exploded);
}

另一个自定义过滤器的良好示例是当您不想公开数据库表的列名时。例如,假设我们不希望公开在users表中存在名为username的列

在User.php中

protected $filters = ['by'];

public function by($query, $value) {
    return $query->where('username', $value);
}

https://example.com?by=dariush123

输出

小贴士

为了防止您的模型变得杂乱或被过滤方法填充,您可以为此创建一个特质,并将有关过滤器的所有内容都放入特质中。

条件过滤器

模型中的$filters属性对该模型来说是全局的。这意味着当您在Eloquent查询上使用filter()方法时,它将始终执行所有的$filters过滤器。

可能存在一些情况,您需要根据条件指定确切要过滤的哪些过滤器。

为了实现这一点,您可以在filter()方法中指定您想要的过滤器作为参数。

示例

在您的查询中

User::filter('in')->get();

in=name,mehrad,reza&like=name,mehrad

输出

如果未指定in参数,则查询的结果将只有一条记录(mehrad)。

另一个示例

在您的查询中

User::filter('like', 'name')->get();

like=name,mehrad,reza,dariush,hossein&name[0]=mehrad&name[1]=hossein&username=mehrad

输出

您的支持很重要

如果您发现这个包很有用,并希望鼓励我维护和改进它,只需按下星号按钮来表示您的意愿。

用一杯茶奖励我 🍵

请用您国家的一杯茶的价值来奖励我,这样我就会有能量来维护这个包。

  • Ethereum: 0x2D5BFdEc132F9F0E9498Fb0B58C800db4007D154