culturegr/filterer

为Eloquent模型添加筛选、排序和分页功能。

v1.3.0 2024-10-03 06:59 UTC

This package is auto-updated.

Last update: 2024-10-03 07:00:24 UTC


README

Packagist Version Total Downloads Github Actions

本包提供了一种简单的方法,可以将筛选排序分页功能添加到Eloquent模型中。

安装

通过Composer

$ composer require culturegr/filterer

用法

假设以下数据库架构

以下是对应于clients表的Client模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Client extends Model
{
    protected $date = ['registered_at'];

    public function country()
    {
        return $this->belongsTo(Country::class);
    }

    public function orders()
    {
        return $this->hasMany(Order::class);
    }

    public function favoriteProducts()
    {
        return $this->belongsToMany(FavoriteProduct::class);
    }

}

重要 Filterer包强烈依赖于Laravel命名约定来命名模型之间的关系。因此,为了使包按预期工作,定义的模型关系应按照这些约定命名

使用特性

可以通过使用Filterer包提供的Filterable特性将筛选、排序和分页功能添加到Client模型中

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use CultureGr\Filterer\Filterable;

class Client extends Model
{
    use Filterable;
    ...
}

定义可筛选和可排序字段

可以显式定义可筛选和/或可排序的字段,分别使用模型上的fiterablesortable属性。可筛选和可排序字段可以存在于模型本身或其一级关系上

  • 存在于模型本身的字段使用列名定义,即columnName
  • 存在于相关模型上的字段使用关系名后跟点.和关联模型上的列名定义,即relationshipName.columnName

例如,为了能够同时按年龄、国家名称、订单项和收藏产品价格筛选和排序Client模型,必须定义以下可筛选和可排序字段

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use CultureGr\Filterer\Filterable;

class Client extends Model
{
    use Filterable;

    protected $filterable = ['age', 'country.name', 'orders.items', 'favoriteProducts.price'];

    protected $sortable = ['age', 'country.name', 'orders.items', 'favoriteProducts.price'];
    ...
}

支持的数据类型和筛选操作符

以下表格列出了在筛选资源时可以执行的数据类型及其对应操作

筛选模型

可以使用(由Filterable特性提供的)filter方法获取筛选后的结果,并将包含具有filters属性的数组的参数传递给该方法,如下所示

Client::filter([
    'filter' => [
        [
            'column' => <FILTERABLE>,
            'operator' => <OPERATOR>,
            'query_1' => <VALUE>,
            'query_2' => null|<VALUE> // query_2 is required only with **between**, **not_between** and **between_date** operators
        ],
        ...
    ]
])->get();

重要:当作为参数传递一个具有limit属性的参数时,filter方法返回一个Eloquent\Builder实例(请参阅分页模型

例如,以下筛选可以应用于筛选年龄在35至40岁之间、来自希腊、在2020年5月1日至5月31日之间下订单、收藏产品价格低于10欧元的客户

  • 按年龄,升序
  • 按国家名称,降序
  • 按订单中的项目数量,升序
  • 按收藏产品的价格,降序
Client::filter([
    'filters' => [
        [
            'column' => 'age',
            'operator' => 'between',
            'query_1' => '35',
            'query_2' => '40'
        ],
        [
            'column' => 'country.name',
            'operator' => 'equal_to',
            'query_1' => 'Greece',
            'query_2' => null
        ],
        [
            'column' => 'orders.shipped_at',
            'operator' => 'between_date',
            'query_1' => '2020-05-1',
            'query_2' => '2020-05-31'
        ],
        [
            'column' => 'favoriteProducts.price',
            'operator' => 'less_than',
            'query_1' => '10',
            'query_2' => null
        ],
    ],
])->get();

排序模型

可以使用filter方法获取排序后的结果,并将包含具有sorts属性的数组的参数传递给该方法,如下所示

Client::filter([
    'sort' => [
        [
            'column' => <SORTABLE>,
            'direction' => <asc|desc>,
        ],
        ...
    ]
])->get();

例如,以下排序可以应用于按以下方式排序客户

  • 按年龄,升序
  • 按国家名称,降序
  • 按订单中的项目数量,升序
  • 按收藏产品的价格,降序
Client::filter([
    'sorts' => [
        [
            'column' => 'age',
            'direction' => 'asc',
        ],
        [
            'column' => 'country.name',
            'direction' => 'desc',
        ],
        [
            'column' => 'orders.items',
            'direction' => 'asc',
        ],
        [
            'column' => 'favoriteProducts.price',
            'direction' => 'desc',
        ],
    ]
])->get();

分页模型

可以使用filter方法获取分页后的结果,并将包含具有limit属性和page属性的数组的参数传递给该方法,如下所示

Client::filter([
    'limit' => <VALUE>,
    'page' => <VALUE>
]);

重要: 当指定了 limit 时,filter 方法将返回一个 LengthAwarePaginator 实例。有关 Laravel 处理分页的更多信息,请参阅 这里

组合过滤、排序和分页

可以使用 Filterable 特性提供的 filter 方法结合过滤、排序和分页功能,并将包含任何三个 filterssorts 以及 limit/page 属性的数组作为参数传递

Client::filter([
    'filter' => [
        ...
    ],
    'sort' => [
        ...
    ],
    'limit' => '...',
    'page' => '...'
]);

查询字符串格式

可以通过解析以下格式的查询字符串来轻松获取 filter 方法的参数

GET http://example.com/clients
    ?filter[0][column]=<FILTERABLE>&filter[0][operator]=<OPERATOR>&filter[0][query_1]=<VALUE1>&filter[0][query_2]=<VALUE2>
    &filter[1][column]=<FILTERABLE>&filter[0][operator]=in&filter[0][query_1][0]=<VALUE1>&filter[0][query_1][1]=<VALUE2>...
    &filter[2][column]=...
    &sort[0][column]=<SORTABLE>&sort[0][direction]=<DIECTION>
    &sort[1][column]=...
    &limit=<LIMIT>
    &page=<PAGE>

测试

$ composer test

许可

请参阅 许可文件 获取更多信息。

致谢