本文目录导读:

在 Laravel 中,API 资源(API Resource)是用于转换和格式化 Eloquent 模型数据为 JSON 响应的强大工具,以下是几种转换方式:
创建 API 资源类
# 创建单个资源 php artisan make:resource UserResource # 创建资源集合 php artisan make:resource UserCollection --collection
基本转换
单个资源
// app/Http/Resources/UserResource.php
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at->format('Y-m-d H:i:s'),
'role' => $this->role->name,
// 自定义字段
'full_name' => $this->first_name . ' ' . $this->last_name,
];
}
}
集合资源
// app/Http/Resources/UserCollection.php
class UserCollection extends ResourceCollection
{
public $collects = UserResource::class;
public function toArray($request)
{
return [
'data' => $this->collection,
'meta' => [
'total' => $this->resource->total(),
'current_page' => $this->resource->currentPage(),
],
];
}
}
在控制器中使用
use App\Http\Resources\UserResource;
use App\Http\Resources\UserCollection;
class UserController extends Controller
{
// 单个模型
public function show($id)
{
$user = User::findOrFail($id);
return new UserResource($user);
}
// 多个模型
public function index()
{
$users = User::paginate(10);
return UserResource::collection($users);
// 或使用集合
// return new UserCollection($users);
}
}
自定义响应格式
添加额外数据
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
// 关联资源
'posts' => PostResource::collection($this->whenLoaded('posts')),
// 条件字段
'secret' => $this->when($request->user()->isAdmin(), $this->secret),
];
}
// 自定义包装
public function with($request)
{
return [
'success' => true,
'version' => '1.0.0',
];
}
}
嵌套资源关系
class PostResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'author' => new UserResource($this->whenLoaded('user')),
'comments' => CommentResource::collection($this->whenLoaded('comments')),
];
}
}
高级转换技巧
条件属性
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
// 仅当关系加载时包含
'profile' => $this->when($this->relationLoaded('profile'), function () {
return new ProfileResource($this->profile);
}),
// 合并条件
$this->mergeWhen($this->isPremium(), [
'premium_features' => $this->premiumFeatures,
'expires_at' => $this->expiresAt,
]),
];
}
}
数据转换回调
class UserResource extends JsonResource
{
public function toArray($request)
{
return $this->transform(function ($user) {
return [
'id' => $user->id,
'name' => $user->name,
];
});
}
}
自定义 JSON 响应
class UserResource extends JsonResource
{
public function withResponse($request, $response)
{
$response->header('X-User-Resource', 'true');
$response->setStatusCode(200); // 自定义状态码
// 修改响应内容
$original = $response->getData();
$original->custom_data = '额外数据';
$response->setData($original);
}
}
资源集合的分页
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
'links' => [
'first' => $this->url(1),
'last' => $this->url($this->lastPage()),
'prev' => $this->previousPageUrl(),
'next' => $this->nextPageUrl(),
],
'meta' => [
'current_page' => $this->currentPage(),
'from' => $this->firstItem(),
'to' => $this->lastItem(),
'per_page' => $this->perPage(),
'total' => $this->total(),
],
];
}
}
最佳实践
- 保持资源类专注:每个资源类只处理一种模型的转换
- 避免业务逻辑:资源类只负责数据转换,不处理业务逻辑
- 使用 whenLoaded:避免 N+1 查询问题
- 缓存转换结果:对于频繁访问的数据
- 统一返回格式:保持 API 响应的一致性
通过 API 资源,你可以清晰地控制数据输出格式,避免在控制器中混合数据转换逻辑。