albetnov / laravel-filterable
基于查询字符串的 Laravel 过滤器
Requires
- php: ^8.1
- illuminate/contracts: ^10.44|11.*
- laravel/framework: ^10.44|11.*
- nesbot/carbon: ^2.67|3.*
- orchestra/testbench: 8.*|9.*
- spatie/laravel-package-tools: ^1.16.0
Requires (Dev)
- laravel/pint: ^1.0
- mockery/mockery: ^1.6
- nunomaduro/collision: ^7.10|8.*
- nunomaduro/larastan: ^2.9
- pestphp/pest: ^2.34.0
- pestphp/pest-plugin-arch: ^2.3
- pestphp/pest-plugin-laravel: ^2.3
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
This package is auto-updated.
Last update: 2024-09-08 01:55:29 UTC
README
Laravel 模型可过滤,可自动根据给定的查询字符串过滤模型
安装
您可以通过 composer 安装此包
composer require albetnov/laravel-filterable
用法
简单地在您的模型中添加 Filterable
特性,并定义 $filterableColumns
或 filterableColumns()
(如果需要额外逻辑)以定义可过滤的列
<?php namespace App\Models; use Albet\LaravelFilterable\Enums\FilterableType; use Albet\LaravelFilterable\Traits\Filterable; use Illuminate\Database\Eloquent\Model; class Flight extends Model { use Filterable; protected arrray $filterableColumns = [ 'ticket_no' => FilterableType::NUMBER, 'customer_name' => FilterableType::TEXT, 'schedule' => FilterableType::DATE ]; protected function filterableColumns(): array { return [ 'customer_address' => FilterableType::custom(), ]; } }
获取可过滤列
如果两者都已定义,则 Filterable 会优先使用方法而不是属性。如: Filterable.php
如果没有定义,则 Filterable 将抛出 PropertyNotExist
异常。
可过滤类型
有五种可过滤类型选项可用
-
数字
此类型将给定负载转换为 float 或 int,具体取决于字符串是否包含 . 前缀(表示 float)或没有(表示 int)。 -
文本
一种用于处理基于文本的过滤器的类型。 -
日期
一种旨在处理基于日期的过滤器的类型。这将把负载转换为 Carbon 格式,并相应地调整查询。 -
布尔值
一种旨在处理基于布尔值的过滤器的类型。此类型将根据0
和1
将负载转换为布尔值。
修饰符
每个 FilterableType
都支持一个修饰符来改变从分配的字段进行过滤的行为。目前您可以使用两个修饰符。
限制
允许您限制可用的运算符,使其他运算符无效并抛出OperatorNotExist
异常。该函数有一个参数,接收一个Operators
数组。用法示例
use Albet\LaravelFilterable\Enums\FilterableType; use Albet\LaravelFilterable\Enums\Operators; protected function filterableColumns(): array { return [ 'customer_name' => FilterableType::TEXT->limit([Operators::CONTAINS, Operators::NOT_CONTAINS, Operators::STARTS_WITH, Operators::ENDS_WITH]) ]; }
相关
允许您将查询替换为使用whereHas
,以便过滤器应用于关系级别。该函数接收两个参数,第一个是关系名称,第二个是可选的额外查询条件。用法示例
use Albet\LaravelFilterable\Enums\FilterableType; use Illuminate\Database\Eloquent\Relations\HasOne; protected function filterableColumns(): array { return [ 'flight_license' => FilterableType::NUMBER->related('flight', fn($query) => $query->where('status', 'A')) ]; } public function flight(): HasOne { $this->hasOne(Flight::class); }
修饰符可以一起使用:
FilterableType::DATE->related()->limit()
以组合条件
自定义类型
自定义类型不支持修饰符。
如前所述,Filterable 有 5 种类型,最后一个是 custom
,它被处理得不同。自定义类型是 FilterableType
的静态方法的一部分,因此您需要在使用 filterableColumns()
方法中定义它。
use Albet\LaravelFilterable\Enums\FilterableType; FilterableType::custom();
自定义方法接受一个参数,$allowedOperators
是一个包含 Operators
的数组。此参数用于定义自定义过滤器的允许操作符白名单。
自定义类型需要一个处理器,处理器和字段都必须按照以下约定定义
use Albet\LaravelFilterable\Enums\FilterableType; use Albet\LaravelFilterable\Enums\Operators; use Albet\LaravelFilterable\Operator; use Albet\LaravelFilterable\Traits\Filterable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class Flight extends Model { use Filterable; public function filterableColumns(): array{ return [ 'customer_address' => FilterableType::custom([Operators::CONTAINS, Operators::NOT_CONTAINS]) ]; } public function filterCustomAddress(Builder $builder, string $operator, string $value): void { dump($operator); // 'contains' or 'not_contains' (raw string operator) dump($value); // raw string value $builder->whereHas('customer', fn($query) => $query->where('name', 'LIKE', "%$value%")); } }
注意,列使用蛇形命名法定义,而方法使用驼峰命名法。您的函数也应定义三个参数。第一个是 Builder
,一个原始 operator
,最后是一个原始 value
。这里的 raw
意味着这些值未经格式化,它们从查询字符串快速传递过来。然而,它们是 经过验证的。
在模型中使用
只需调用过滤作用域即可
<?php use App\Models\Flight; // In this example I choose to merge the request, alternatively you can hit endpoint like this: // https://:8000/all-flights?filters[0][field]=customer_name&filters[0][operator]=eq&filters[0][value]=asep request()->merge([ 'filters' => [ [ 'operator' => 'eq', 'field' => 'customer_name', 'value' => 'asep' ] ] ]); dd(Flight::filter()->get()); // Flight[{customer_name: "asep", ticket_no: 20393, schedule: "2023-08-20"}]
请求模式
以下是 Laravel Filterable 可以读取的预期请求负载模式
{ "filters": [ { "operator": "eq", "field": "customer_name", "value": "asep" } ] }
所有过滤器都必须放置在 filters
键下,值应该是包含以下内容的 object
数组
fields
(字符串)
确定应过滤哪个字段operator
(字符串)
在过滤上下文中使用哪种操作符value
(字符串)
预期的值
上述模式映射到查询字符串时将如下所示
?filters[0][field]=customer_name&filters[0][operator]=eq&filters[0][value]=asep
支持的操作符
eq
:检查值是否等于指定的输入。neq
:检查值是否不等于指定的输入。contains
:检查值是否包含指定的输入。starts_with
:检查值是否以指定的输入开头。ends_with
:检查值是否以指定的输入结尾。not_contains
:检查值是否不包含指定的输入。in
(数组):检查值是否是指定的输入之一。not_in
(数组):检查值是否不是指定的任何输入。have_all
(数组):检查值是否包含所有指定的输入。gt
:检查值是否大于指定的输入。lt
:检查值是否小于指定的输入。gte
:检查值是否大于或等于指定的输入。lte
:检查值是否小于或等于指定的输入。
限制
值仅限于 字符串
类型,并且每个转换都是通过在 filterableColumns
中定义的类型来执行的。对于包含 ,
作为值分隔符的 数组
,可能会发生模糊转换。请避免在您的值中使用 ,
,因为它们用作内部数组分隔符。另一种情况可能涉及包含多个 .
分隔符的 数字
。
测试
composer test
变更日志
请参阅变更日志,了解最近有哪些更改。
贡献
请参阅贡献指南以获取详细信息。
安全漏洞
请参阅我们的安全策略,了解如何报告安全漏洞。
鸣谢
许可
MIT 许可证 (MIT)。请参阅许可文件获取更多信息。