brainstud/json-api-resource

构建符合 JSON:API 标准的 Laravel API 资源


README

使用 Brainstud\JsonApi 包使您的 Laravel API 符合 JSON:API 标准。

示例用法

// Course.php

/**
 * @property int $id
 * @property string $title
 * @property string $description
 * @property Carbon $created_at
 * @property Collection $enrollments
 */
class Course extends Model 
{
    protected $fillable = [
        'title',
        'description',
    ];
    
    public function enrollments(): HasMany
    {
        return $this->hasMany(Enrollment::class);
    }
}

// CourseResource.php

/**
 * @property Course $resource 
 */
class CourseResource extends JsonApiResource
{
    protected function register(): array
    {
        return [
            'id' => $this->resource->id,
            'type' => 'courses',
            'attributes' => [
                'title' => $this->resource->title,
                'description' => $this->resource->description,
                'created_at' => $this->resource->created_at->format('c'),
            ],
            'relationships' => [
                'enrollments' => ['enrollments', EnrollmentResourceCollection::class],
            ],
        ];
    }
}

// CoursesController.php

class CoursesController
{
    public function index(IndexCoursesRequest $request)
    {
        $query = (new CoursesQueryBuilder)->jsonPaginate();
        return new CourseResourceCollection($query);
    }
    
    public function show(ShowCourseRequest $request, Course $course)
    {
        $query = (new CoursesQueryBuilder)->find($course->id);
        return new CourseResource($query);
    }
}

安装

需要此包

composer require brainstud/json-api-resource

用法

  • 让资源对象从 JsonApiResource 继承,而不是从 JsonResource 继承。
  • 实现一个返回以下数组的 register 方法。register 方法可以访问 $this->resource,其中包含当前模型
protected function register(): array
{
    return [
        'id' => $this->resource->identifier,
        'type' => 'object_type',
        'attributes' => [
            'field' => $this->resource->field,
            'other_field' => $this->resource->other_field,
        ],
        'relationships' => [
            'items' => ['items', ItemsResourceCollection::class],
            'item' => ['item', ItemResource::class],
        ],
        'meta' => [
            'some_data' => 'some value',         
        ],
    ];
}

关系

JSON:API: Includes 要包含关系,它们需要被加载。这可以通过实现一个 ?include 参数或使用 spatie/laravel-query-builder 来完成。

调整响应

register 方法不像 JsonResourcetoArray 方法那样可以访问 $request。如果您想根据请求操作响应,可以通过重写 addToResponse 方法来实现。

protected function addToResponse($request, $response): array
{
    if ($this->requestWantsMeta($request, 'data')
        && ($data = $this->getData())
    ) {
        $response['meta']['data'] = $data;
    }

    return $response;
}

资源深度

资源深度默认为 2。可以通过向资源传递一个数组来更改它,其中第二个元素是所需的资源深度。在以下示例中,我们使用了深度为 3

public function show(ShowCourseRequest $request, Course $course)
{
    $query = (new CoursesQueryBuilder)->find($course->id);
    return new CourseResource([$query, 3]);
}

这允许我们请求嵌套 3 层的包含:/courses/{identifier}?include=content,content.answers,content.answers.feedback

异常处理器

此包包含一个异常处理器,可以将异常渲染为 JSON:API 错误消息。可以直接通过编辑 app.php 并注册此单例来使用此处理器

// app.php
$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    \Brainstud\JsonApi\Handlers\JsonApiExceptionHandler::class
);

或注册自己的异常处理器并将渲染委托给 JsonApiExceptionHandler::render 方法。

// app.php
$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

// handler.php
public function render($request, Throwable $exception)
{
    if ($request->wantsJson()) {
        return (new JsonApiExceptionHandler($this->container))->render($request, $exception);
    }

    return parent::render($request, $exception);
}

返回错误响应

有多种方式可以返回错误页面

// Throw an exception that will be handled by the JsonApiExceptionHandler
throw new UnprocessableEntityHttpException();

// Return a defined error response
return (new UnprocessableEntityError)->response();

// Return a custom error response
return ErrorResponse::make(new DefaultError(
    'PROCESSING_ERROR',
    'Could not save item',
    'An error occurred during saving of the item'
), Response::HTTP_INTERNAL_SERVER_ERROR);

许可证

JsonApi 是开源软件,根据 MIT 许可证 许可