aros / omnifetch-lumen
简化 fetch API 端点的 Lumen 获取库
Requires
- php: >=7.0
This package is auto-updated.
Last update: 2024-09-11 16:30:56 UTC
README
OmniFetch for Lumen 是一个有用的库,它使 fetch API 端点更容易设置,并且足够灵活,适用于不同的情况。该库允许通过在请求中传递查询参数来动态修改响应数据集。这些修改可以包括应用过滤器、嵌入相关数据和分页,以及使用分组来聚合数据。
安装
$ composer require aros/omnifetch-lumen
依赖关系
- Lumen >= 5.5
主要功能
OmniFetch 只有两个方法可以使用。如下所示
- OmniFetch::getSingle(Illuminate\Database\Eloquent\Builder $builder, array $params) - 用于获取单个记录。
- OmniFetch::paginate(Illuminate\Database\Eloquent\Builder $builder, array $params) - 用于获取记录列表
所使用的构建器应使用模型(即主模型)创建。例如 Author::query()
参数选项
OmniFetch::getSingle 和 OmniFetch::paginate 都需要其参数中的 $params,这是一个包含选项的关联数组。
-
filters(数据类型:JSON 列表/数组):向查询添加条件。它可以接受所需的所有条件。每个条件都是一个 JSON 对象(如果 filters 是一个 JSON 列表,则此格式最好如果作为请求查询参数传递),或一个关联数组(如果 filters 是一个数组)。它包含以下字段
- field(必需):用于过滤的字段。它可以是主模型或相关模型(可以通过在主模型中指定的关系名称后面加上关系字段来实现。例如 *author.rating *)。它支持嵌套关系字段,例如 author.publisher.is_local。
- value(必需):要使用的值。
注意:如果值中使用 %,则如果作为请求查询参数传递,则需要对其进行 URL 编码。
- cond_op(可选 | 默认:'='):比较字段和值时使用的条件运算符。可用的运算符包括:=,!=,>,<,>=,<=,LIKE,IS_NULL(仅需要 field),IS_NOT_NULL(仅需要 field)。
- logical_op(可选 | 默认:'AND'):在它之后结合剩余过滤器的逻辑运算符。可用的运算符包括 AND 和 OR。
示例:
[{"field": "status_id", "value": 1}]=>... WHERE primary_table.status_id = 1;[{"field": "name", "value": "%25rich%25", "cond_op": "LIKE"}]=>... WHERE primary_table.name LIKE "%rich%";[{"field": "status_id", "value": 1}, {"field": "author.rating", "value": 2.5, "cond_op": ">="}]=>... WHERE primary_table.status_id = 1 AND author.rating >= 2.5[{"field": "likes", "value": 100, "cond_op": ">", "logical_op": "OR"}, {"field": "rating", "value": 4.0, "cond_op": ">="}, {"field": "rating", "value": 4.5, "cond_op": "<="}]=>... WHERE primary_table.like > 100 OR (primary_table.rating >= 4.0 AND primary_table.rating <= 4.5)
-
embeds(数据类型:JSON 列表/数组):将相关模型数据嵌入到正在获取的主模型中。仅允许主模型的关联关系名称及其关联关系(这意味着允许嵌套关系)。
示例 :
["status", "author.publisher"]
-
no_pages(数据类型:布尔值 | 默认为 false):指定是否分页。
-
page(数据类型:整数 | 默认:1):指定分页时的当前页。
-
page_size (数据类型:整数 | 默认:20):指定分页时每页返回的记录数
-
order_by (数据类型:字符串):指定排序的字段(目前不支持关联字段)。
-
is_asc (数据类型:布尔值 | 默认:true):指定排序方向
-
aggs (数据类型:JSON列表/数组):用于执行求和、最小值和最大值等聚合操作。列表中指定的每个聚合都是一个JSON对象(如果aggs是一个JSON列表)或关联数组(如果aggs是一个数组)。以下是可以用于每个聚合的字段
-
field (必需):要聚合的字段。这可以是关联字段的字段。允许嵌套关联。
注意:为了使用关联字段,主模型必须具有
OmniFetch\HasJoinWith特征。 -
alias (必需):用于聚合的别名。
-
func (必需):聚合函数。以下是可以用的函数
- count =>
COUNT({{col}}) - avg =>
AVG({{col}}) - min =>
MIN({{col}}) - max =>
MAX({{col}}) - sum =>
SUM({{col}})
- count =>
示例:
[{"field": "likes", "func": "sum", "alias": "total_likes"}]=>SELECT SUM(primary_table.likes) AS total_likes ...
-
-
group_by (数据类型:JSON列表/数组):用于分组数据。每个分组列由一个JSON对象表示(如果group_by是一个JSON列表)或关联数组(如果group_by是一个数组)。以下是可以用于每个分组的字段
-
field (必需):用于分组的字段。这可以是关联字段的字段。允许嵌套关联。
注意:要使用关联字段,主模型必须具有
OmniFetch\HasJoinWith特征。 -
func (可选):分组函数。以下是可以用的函数
- date =>
DATE({{col}}) - month =>
DATE_FORMAT({{col}}, '%Y-%m') - year =>
YEAR({{col}})
- date =>
-
alias (如果使用func则为必需):用于分组的别名。
示例:
[{"field": "created_at", "func": "date", "alias": "created_date"}]=>... GROUP BY DATE(primary_table.created_at) AS created_date
-
用法
可以通过一个例子来说明。在这个例子中,创建了getOnePost和getAllPosts端点。使用的模型(或实体)是
- Publisher:一家雇佣作者撰写帖子的公司。
- Author:撰写帖子并属于publisher的人。
- Post:由作者撰写的内容。
在这个例子中,Post是主模型,而Author和Publisher是相关模型。
注意:为了使库非常有效,模型关系应该设置良好
首先,让我们设置模型(假设已完成数据库迁移和其他项目先决条件)
出版商模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; /** * Class Publisher * @package App\Models * * @property integer $id * @property string $name * @property string $address * @property boolean $is_local * @property string $created_at * @property string $modified_at * @property integer $status_id */ class Publisher extends Model { protected $table = 'publishers'; public $timestamps = false; }
作者模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * Class Author * @package App\Models * * @property integer $id * @property integer $publisher_id * @property string $first_name * @property string $last_name * @property float $rating * @property string $created_at * @property string $modified_at * @property integer $status_id */ class Author extends Model { protected $table = 'authors'; public $timestamps = false; /** * @return BelongsTo */ public function publisher() { return $this->belongsTo(Publisher::class, 'publisher_id'); } }
帖子模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use OmniFetch\HasJoinWith; /** * Class Post * @package App\Models * * @property integer $id * @property integer $author_id * @property string $title * @property string $content * @property float $rating * @property integer $likes * @property string $created_at * @property string $modified_at * @property integer status_id */ class Post extends Model { use HasJoinWith; protected $table = 'posts'; public $timestamps = false; /** * @return BelongsTo */ public function author() { return $this->belongsTo(Author::class, 'author_id'); } }
其次,让我们设置控制器
<?php namespace App\Http\Controllers; use App\Models\Post; use Illuminate\Http\Request; use OmniFetch\OmniFetch; class ExampleController extends Controller { public function fetchAllPosts(Request $request) { $data = (new OmniFetch())->paginate(Post::query(), $request->query()); return response()->json($data); } public function fetchOnePost(Request $request, $post_id) { $post = (new OmniFetch())->getSingle(Post::where('id', $post_id), $request->query()); return response()->json($post->toArray()); } }
最后,添加路由(我们完成了!)
<?php // routes/web.php $router->get('/posts', ['uses' => 'ExampleController@fetchAllPosts']); $router->get('/posts/{post_id}', ['uses' => 'ExampleController@fetchOnePost']);
带有响应的请求示例
-
GET {{base_url}}/posts/1?embeds=["author"]响应
点击以显示响应
{ "id": 1, "author_id": 101, "title": "Quis ut exercitationem nihil nemo quos aut numquam doloribus.", "content": "Nisi rerum harum reprehenderit. Rem commodi non dolorum repellendus. Quibusdam nobis voluptatibus illum alias voluptatem. Earum dolorem aspernatur quia sint.", "rating": 0.48, "likes": 95, "created_at": "1980-01-18 18:52:07", "modified_at": "1994-02-01 18:58:16", "status_id": 1, "author": { "id": 101, "publisher_id": 26, "first_name": "Mellie", "last_name": "Casper", "rating": 2.47, "created_at": "1995-02-14 08:41:00", "modified_at": "1985-10-23 13:17:36", "status_id": 1 } } -
GET {{base_url}}/posts?page=3&page_size=2&filters=[{"field": "author.rating", "value": 3.5, "cond_op": ">"}]&embeds=["author.publisher"]&order_by=likes&is_asc=0响应
点击以显示响应
{ "pagination": { "total_count": 142, "total_pages": 71, "current_page": 3, "count": 2 }, "list": [ { "id": 325, "author_id": 220, "title": "Tempore aperiam eum itaque voluptates illo dolor.", "content": "Qui nemo delectus iste sequi voluptates impedit beatae. Accusamus eligendi qui tenetur voluptatum maxime. Sapiente blanditiis omnis deserunt suscipit voluptates.", "rating": 1.19, "likes": 2440, "created_at": "2019-04-06 12:32:59", "modified_at": "2019-05-27 11:15:37", "status_id": 1, "author": { "id": 220, "publisher_id": 73, "first_name": "Serena", "last_name": "Bernier", "rating": 4.58, "created_at": "2012-06-21 11:27:25", "modified_at": "2012-06-21 12:36:46", "status_id": 1, "publisher": { "id": 73, "name": "Prosacco-Lueilwitz", "address": "126 Clarissa Wells West Blanca, WY 11801", "is_local": 0, "created_at": "2001-04-01 08:02:02", "modified_at": "2001-04-01 08:02:02", "status_id": 1 } } }, { "id": 204, "author_id": 235, "title": "Officia est in exercitationem veniam libero quo sed.", "content": "Commodi tempore a harum aut magni. Ad harum natus minima eos amet. Doloribus sequi veritatis voluptatem sint voluptates deleniti. Id et explicabo et dolores exercitationem et nam.", "rating": 0.67, "likes": 2435, "created_at": "2019-11-05 13:02:07", "modified_at": "2019-11-30 07:38:01", "status_id": 1, "author": { "id": 235, "publisher_id": 91, "first_name": "Alexzander", "last_name": "Kemmer", "rating": 4.64, "created_at": "2001-09-07 23:24:12", "modified_at": "2001-09-07 23:24:12", "status_id": 1, "publisher": { "id": 91, "name": "Smitham LLC", "address": "029 Pierre Greens Apt. 445 South Mallory, SC 88096", "is_local": 1, "created_at": "1995-08-15 21:46:30", "modified_at": "1995-08-15 21:46:30", "status_id": 1 } } } ] } -
GET {{base_url}}/posts?aggs=[{"field": "author.rating", "func": "avg", "alias": "average_rating"}]&group_by=[{"field": "author.publisher.name", "alias": "publisher_name"}]&page_size=3注意:当使用aggs或group_by时,限制返回的字段为aggs和group_by字段
响应
点击以显示响应
{ "pagination": { "total_count": 89, "total_pages": 30, "current_page": 1, "count": 3 }, "list": [ { "publisher_name": "Ankunding Ltd", "average_rating": 1.6022222108311 }, { "publisher_name": "Bashirian-Altenwerth", "average_rating": 3.2622222635481 }, { "publisher_name": "Baumbach Ltd", "average_rating": 3.0066666603088 } ] }