LaravelAPI资源怎么转换

wen PHP项目 3

本文目录导读:

LaravelAPI资源怎么转换

  1. 创建 API 资源类
  2. 基本转换
  3. 在控制器中使用
  4. 自定义响应格式
  5. 嵌套资源关系
  6. 高级转换技巧
  7. 自定义 JSON 响应
  8. 资源集合的分页
  9. 最佳实践

在 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(),
            ],
        ];
    }
}

最佳实践

  1. 保持资源类专注:每个资源类只处理一种模型的转换
  2. 避免业务逻辑:资源类只负责数据转换,不处理业务逻辑
  3. 使用 whenLoaded:避免 N+1 查询问题
  4. 缓存转换结果:对于频繁访问的数据
  5. 统一返回格式:保持 API 响应的一致性

通过 API 资源,你可以清晰地控制数据输出格式,避免在控制器中混合数据转换逻辑。

抱歉,评论功能暂时关闭!