emeguan / laravel-resources
为Laravel Eloquent扩展了额外功能:API资源,允许您通过URL选择要返回的属性和关系
0.0.10
2023-12-12 09:21 UTC
Requires
- php: >=7.0.0
README
为Laravel Eloquent扩展了额外功能:API资源,允许您通过URL选择要返回的属性和关系
介绍
当我们从Laravel创建JSON API时,我们可以用多种方式实现,我认为最常用的方式是创建REST API。如果我们想使用json:api规范,或者使用已经为Laravel提供的一些优秀库,如
但是,我们的API可能无法满足REST API的标准方法,我们可能更希望有额外的参数,以便在返回JSON格式之前对数据进行不同的查询。
在这种情况下,我们可以使用Eloquent生成查询,并使用toJson方法返回数据。
通过使用Laravel Eloquent: API Resources,我们可以以静态方式控制每个模型想要返回的属性和关系。通过我们这里的小库,我们可以从URL的参数动态修改API资源。
安装
使用Composer安装
composer require emeguan/laravel-resources
要求
我还没有测试过,但它应该适用于包括Eloquent API Resources在内的任何Laravel版本,即Laravel 5.5及以后版本。
代码已在Laravel 9上进行了测试
使用
模型
class A extends Model { use HasFactory; use \EmeGuan\Resources\ModelTrait; //<--
控制器
Route::get('/as', function () { $as=A::all(); return new \EmeGuan\Resources\Collection($as); }); Route::get('/a/{id}', function ($id) { $a=A::find($id); return new \EmeGuan\Resources\Resource($a); //<-- });
调用
http://laravel-resource.local/as
{
"data": [
{
"id": 1,
"name": "A1",
"created_at": "2023-02-06 16:55:52",
"updated_at": "2023-02-06 16:55:52"
},
{
"id": 2,
"name": "A2",
"created_at": "2023-02-06 16:55:52",
"updated_at": "2023-02-06 16:55:52"
},
http://laravel-resource.local/a/1
{
"data": {
"id": 1,
"name": "A1",
"created_at": "2023-02-06 16:55:52",
"updated_at": "2023-02-06 16:55:52"
}
}
文档
在URL中,我们可以指定模型所需的属性和要包含的关系。让我们用一个例子来看一下。
我们从这些5个模型开始
class A extends Model { use HasFactory; use ModelTrait; protected $fillable = [ 'id', 'name']; public function bs() { return $this->hasMany(B::class); } public function ds() { return $this->hasMany(D::class); } } class B extends Model { use HasFactory; use ModelTrait; protected $fillable = [ 'id', 'name', 'a_id']; public function cs() { return $this->hasMany(C::class); } public function a() { return $this->belongsTo(A::class); } } class C extends Model { use HasFactory; use ModelTrait; protected $fillable = [ 'id', 'name', 'b_id']; public function b() { return $this->belongsTo(B::class); } } class D extends Model { use HasFactory; use ModelTrait; protected $fillable = [ 'id', 'name', 'a_id']; public function es() { return $this->hasMany(E::class); } public function a() { return $this->belongsTo(A::class); } } class E extends Model { use HasFactory; use ModelTrait; protected $fillable = [ 'id', 'name', 'd_id']; public function d() { return $this->belongsTo(D::class); } }
- 获取所有A,只包含id和name属性
http://laravel-resources.local/as?fields[as]=id,name
{
"data": [
{
"id": 1,
"name": "A1"
},
{
"id": 2,
"name": "A2"
},
{
"id": 3,
"name": "A3"
},
{
"data": [
{
"id": 1,
"name": "A1",
"bs": [
{
"name": "B1"
},
{
"name": "B2"
},
{
"name": "B3"
}
]
},
{
"id": 2,
"name": "A2",
"bs": [
{
"name": "B4"
},
{
"name": "B5"
},
{
"name": "B6"
}
]
},
{
"id": 3,
"name": "A3",
"bs": [
{
"name": "B7"
},
{
"name": "B8"
}
]
},
- 我们可以使用点表示法包含多级关系。
http://laravel-resources.local/as?include=bs.cs&fields[as]=id,name&fields[bs]=name
{
"data": [
{
"id": 1,
"name": "A1",
"bs": [
{
"name": "B1",
"cs": [
{
"id": 1,
"name": "C1",
"b_id": 1,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
},
{
"id": 2,
"name": "C2",
"b_id": 1,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
},
{
"id": 3,
"name": "C3",
"b_id": 1,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
}
]
},
{
"name": "B2",
"cs": [
{
"id": 4,
"name": "C4",
"b_id": 2,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
},
{
"id": 5,
"name": "C5",
"b_id": 2,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
},
{
"id": 6,
"name": "C6",
"b_id": 2,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
}
]
},
{
"name": "B3",
"cs": [
{
"id": 7,
"name": "C7",
"b_id": 3,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
},
{
"id": 8,
"name": "C8",
"b_id": 3,
"created_at": "2023-02-06 16:57:18",
"updated_at": "2023-02-06 16:57:18"
}
]
}
]
},
{
"id": 2,
"name": "A2",
"bs": [
如果没有指定属性,则返回所有属性。
所有关系都使用点表示法包含,在示例中不需要指定include=bs,bs.cs
- 我们可以包含belongsTo关系
http://laravel-resources.local/bs?fields[bs]=name,a&fields[a]=id,name
{
"data": [
{
"name": "B1",
"a": {
"id": 1,
"name": "A1"
}
},
{
"name": "B2",
"a": {
"id": 1,
"name": "A1"
}
},
{
"name": "B3",
"a": {
"id": 1,
"name": "A1"
}
},
- 如果您需要所有属性和某些关系,可以使用*来替换所有属性
http://laravel-resources.local/bs?fields[bs]=*,a&fields[a]=id,name
{
"data": [
{
"id": 1,
"name": "B1",
"a": {
"id": 1,
"name": "A1"
}
},
{
"id": 2,
"name": "B2",
"a": {
"id": 1,
"name": "A1"
}
},
{
"id": 3,
"name": "B3",
"a": {
"id": 1,
"name": "A1"
}
},
{
"data": [
{
"id": 1,
"name": "A1",
"created_at": "2023-02-06 16:55:52",
"updated_at": "2023-02-06 16:55:52",
"bs": [
{
"name": "B1"
},
{
"name": "B2"
},
{
"name": "B3"
}
],
"ds": [
{
"name": "D1"
},
{
"name": "D2"
},
{
"name": "D3"
}
]
},
{
"id": 2,
"name": "A2",
"created_at": "2023-02-06 16:55:52",
"updated_at": "2023-02-06 16:55:52",
"bs": [
{
"name": "B4"
},
{
"name": "B5"
},
{
"name": "B6"
}
],
"ds": [
{
"name": "D4"
},
{
"name": "D5"
},
{
"name": "D6"
}
]
},
- 您可能需要创建多个返回相同集合但具有不同功能的方法。没有问题,因为主关系的名称是从模型集合表的名称中获取的。
http://laravel-resources.local/as-call-1?fields[as]=id,name
{
"data": [
{
"id": 1,
"name": "A1"
},
{
"id": 2,
"name": "A2"
},
{
"id": 3,
"name": "A3"
},
{
"id": 4,
"name": "A4"
},
{
"id": 5,
"name": "A5"
},
待办事项
- 当我们包含二级关系,并且一级关系没有指定任何属性时(使用fields[relationship]=),会返回类似这样的输出
http://laravel-resources.local/as?include=bs.cs&fields[as]=id&fields[bs]=&fields[cs]=name
{
"data": [
{
"id": 1,
"bs": [
{
"cs": [
{
"name": "C1"
},
{
"name": "C2"
},
{
"name": "C3"
}
]
},
{
"cs": [
{
"name": "C4"
},
{
"name": "C5"
},
{
"name": "C6"
}
]
},
{
"cs": [
{
"name": "C7"
},
{
"name": "C8"
}
]
}
]
},
可能会返回类似这样的输出,其中一级关系没有出现
{
"data": [
{
"id": 1,
"cs": [
{
"name": "C1"
},
{
"name": "C2"
},
{
"name": "C3"
},
{
"name": "C4"
},
{
"name": "C5"
},
{
"name": "C6"
},
{
"name": "C7"
},
{
"name": "C8"
}
]
},
- ...
许可证
Laravel API Resources是开源软件,许可协议为MIT许可。