Laravel Api Resource

Laravel 不使用第三方包,实现 API 功能。

参考:

生成资源

1
2
3
4
5
# 生成 User资源
php artisan make:resource User

# 生成 User资源集合
php artisan make:resource UserCollection

app/Http/Resources/User.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Book as BookResource;

class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
// $this 代表 User 实例
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->phone,

];
}
}

资源的使用

routes/api.php

1
2
3
4
5
6
...

// new UserResource()包裹查询结果
Route::get('/info/', function () {
return new UserResource(App\Models\User::find(1));
});

单个资源
单个资源

资源集合的使用

1
2
3
4
5
6
7
8
9
10
...

Route::get('/user', function () {
return UserResource::collection(User::all());
});

# 自定义的资源集合 UserCollection
Route::get('/users', function () {
return new UserCollection(User::all());
});

自定义资源集合

app/Http/Resources/BookCollection.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class BookCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data'=>$this->collection,
'link'=>'link-value'
];
}
}


自定义资源集合

资源关联

直接关联

User和Book关联,一个读者有多本书。

app/Models/User.php

1
2
3
4
5
6
...

public function books()
{
return $this->hasMany(Book::class);
}

app/Http/Resources/User.php

1
2
3
4
5
6
7
8
9
10
11
12
...

public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->phone,
'book'=>BookResource::collection($this->books),

];
}

routes/api.php

1
2
3
4
5
...

Route::get('/info/related', function () {
return new UserResource(App\Models\User::find(1));
});

关联的操作放在 Resource中完成,路由中没有参与。

条件关联

app/Http/Resources/User.php

1
2
3
4
5
6
7
8
9
10
11
12
...

public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->phone,
'book'=>BookResource::collection($this->whenLoaded('books')),

];
}

routes/api.php

1
2
3
4
5
...

Route::get('/info/condition', function () {
return new UserResource(App\Models\User::find(1)->load('books'));
});

关联的操作路由和 Resource中都有出现。路由中取消load(‘books’),响应中不会出现book数据,符合条件关联。

Include机制

如果客户端只是显示一下所有话题的标题,但是接口却返回了所有相关的数据,不仅做了额外的查询,还增加了响应的数据.
最好的做法应该是客户端想要什么,我们就返回什么资源的数据,客户端应该提供参数,告诉接口是否需要相关的其他资源。

1
$ composer require spatie/laravel-query-builder

扩展包的使用

扩展包针对的是资源集合。

app/Http/Controllers/Api/UsersController.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

use Spatie\QueryBuilder\QueryBuilder;
use Spatie\QueryBuilder\AllowedFilter;
use App\Http\Resources\User as UserResource;

class UsersController extends Controller
{
// allowedIncludes('books') model中定义的books()方法。
// allowedFilters过滤器,例如 ’name',模糊搜索对应的 name值
public function index()
{
$users = QueryBuilder::for(User::class)
->allowedIncludes('books')
->allowedFilters([
'name'
])
->paginate();

return UserResource::collection($users);

}
}

app/Http/Resources/User.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Book as BookResource;

class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->phone,
// 条件关联
'book'=>BookResource::collection($this->whenLoaded('books'))

];
}
}

routes/api.php

1
2
3
4
5
...

Route::namespace('Api')->group(function (){
Route::get('/users/','UsersController@index');
});


Include机制