matthenning / eloquent-api-filter
一种出色且简单的方法,通过API URL直接过滤Eloquent查询,无需杂乱无章。
Requires
- php: >=8.2
- illuminate/database: >=9.0
- illuminate/http: >=9.0
- illuminate/routing: >=9.0
- illuminate/support: >=9.0
This package is auto-updated.
Last update: 2024-09-27 00:15:37 UTC
README
Eloquent API Filter
一种出色且简单的方法,通过仅几行代码创建、查询和修改Eloquent模型,通过API实现。
概念
在开发API应用程序时,你可能会在控制器中遇到大量的重复代码。Eloquent API Filter通过定义一个路由和微小的控制器提供了一个简单的方法来通过API公开你的模型。你的控制器只需要使用几个特性,你将通过API公开你的模型获得完整的CRUD实现。
目录
安装
包安装
composer require matthenning/eloquent-api-filter
控制器设置
你可以选择以下方法之一来利用过滤功能。开箱即用的最简单方法是简单地扩展包含的控制器。
选项1:扩展控制器(推荐)
使用Eloquent API Filter的最简单方法是扩展其控制器。例如,假设你有一个名为Person的模型。你只需创建一个匹配的控制器并使用包含的特性来启用index、show、store、update、destroy的默认方法。
use Matthenning\EloquentApiFilter\Controller; class PersonController extends Controller { use UsesDefaultIndexMethodTrait, UsesDefaultShowMethodTrait, UsesDefaultStoreMethodTrait, UsesDefaultUpdateMethodTrait, UsesDefaultDestroyMethodTrait; }
接下来,你可以通过添加一个新的路由来公开你的控制器
Route::resource('persons', \App\Http\Controllers\PersonController::class);
Eloquent API Filter将自动找到匹配的模型类,只要你遵循此示例的命名约定。如果你有自定义名称或命名空间,你可以在控制器中覆盖modelName属性
protected ?string $modelName = Person::class;
完成!按照方法指南开始查询你的API。有关store、show、index、update、destroy操作,请参阅https://laravel.net.cn/docs/10.x/controllers#actions-handled-by-resource-controller
POST /api/persons { "name": "Alexander", "age": 23 } GET /api/persons/1 GET /api/persons/?filter[age]=23 PUT /api/persons/1 { "age": 24 } DELETE /api/persons/1
自定义资源
如果你使用自定义资源(https://laravel.net.cn/docs/master/eloquent-resources),你可以在模型上定义resourceName属性。否则将使用默认资源。请确保覆盖toArray并调用enrich()来处理你的数据。enrich方法将确保所有预加载的关系(/model?with[]=relation1,relation2)也被它们各自资源转换。
在你的Person模型中
public static ?string $resourceName = PersonResource::class;
在你的PersonResource中
class PersonResource extends \Matthenning\EloquentApiFilter\Resource { public function toArray(Request $request): array { return $this->enrich([ 'id' => $this->resource->id, // ... map your fields here ]); } }
选项2:使用特性
如果你想要完全自己处理控制器和资源逻辑,可以在控制器中使用FiltersEloquentApi特性。
class PersonController extends Matthenning\EloquentApiFilter\Controller { use Matthenning\EloquentApiFilter\Traits\FiltersEloquentApi; public function index(Request $request) { $persons = Person::query(); return $this->filterApiRequest($request, $persons); } }
选项3:直接查询过滤
如果你不喜欢特性,你也可以自己初始化Eloquent API Filter。
use Matthenning\EloquentApiFilter\EloquentApiFilter; class PersonController extends Controller { public function index(Request $request) { $query = Person::query(); $filtered = (new EloquentApiFilter($request, $query))->filter(); return $filtered->get(); } }
查询
过滤
URL语法
使用特定操作符进行过滤
GET /model?filter[field]=operator:comparison
过滤等于
GET /model?filter[field]=operator
操作符
- eq(相等,可以省略)
- ne(不等)
- ge(大于或等于)
- gt(大于)
- le(小于或等于)
- lt(小于)
- in(期望以逗号分隔的数组作为值)
- notin(期望以逗号分隔的数组作为值)
- null
- notnull
- like
- notlike
- today(用于时间戳)
- nottoday(用于时间戳)
示例
匹配所有以Rob开头且已故为null的实体
GET /persons?filter[name]=like:Rob*&filter[deceased]=null:
可以在一个字段上使用多个过滤器进行链式操作。匹配所有created_at在2016-12-10和2016-12-08之间的实体
GET /persons?filter[created_at]=lt:2016-12-10:and:gt:2016-12-08`
通过点符号使用相关模型的字段进行过滤。匹配所有包含"API"的Person的Posts
GET /persons?filter[posts.name]=like:*API*
获取所有名为Rob和Bob的人员
GET /persons?filter[name]=in:Rob,Bob
特殊过滤器
时间戳
匹配今天生日的人员
GET /persons?filter[birthday]=today
排序
URL语法
GET /model?orderBy[field]=direction
示例
限制和排序。匹配年龄为21岁或以上且按姓名升序排列的前10个人
GET /persons?filter[age]=ge:21&order[name]=asc&limit=10
选择字段
仅选择特定列。可能需要在模型转换上做额外工作。
URL语法
GET /model?select=column1,column2
示例
GET /persons?select=name,email
连接
URL语法
GET /model?with[]=relation1 GET /model?with[]=relation1&filter[relation1.field]=operator:comparison
示例
在人员上连接posts-relation
GET /persons?with[]=posts
复杂的过滤器值
如果您需要过滤包含特殊字符的值,可以将字段进行base64编码以避免破坏过滤器语法。
URL语法
GET /model?filter[field]={{b64(value)}}
示例
GET /model?filter[field]=lt:{{b64(MjAxNy0wNy0yMiAyMzo1OTo1OQ==)}}
响应
响应始终包含两个JSON对象:数据和元数据。数据包含查询的模型,而元数据包含例如分页详情。
示例
{ "meta": { "pagination": { "items": 10, "total_items": 113, "total_pages": 12, "current_page": 1, "per_page": 10 } }, "data": [ { "id": 1, "name": "Alexander", "age": 23 }, { /*...*/ }, { /*...*/ } ] }
如果需要更多功能呢?
如果您需要复杂的查询,而这些查询超出了此库的范围,您可以在自定义控制器中使用EloquentApiFilter特质,并在检索模型之前进一步过滤查询。这样,您仍然可以使用过滤器功能,只需在返回检索到的模型之前添加自定义过滤即可。