brainstud / json-api-resource
Build JSON:API compliant Laravel API resources
Installs: 2 524
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 2
Requires
- php: ^8.1
- laravel/framework: ^8.0 || ^9.0 || ^10.0
Requires (Dev)
- laravel/pint: ^1.14
- orchestra/testbench: ^7.22.0
- phpunit/phpunit: ^9.6.3
- dev-main
- v4.0.2
- v4.0.1
- v4.0.0
- v3.1.11
- v3.1.10
- v3.1.9
- v3.1.8
- v3.1.7
- v3.1.6
- v3.1.5
- v3.1.4
- v3.1.3
- v3.1.2
- v3.1.1
- v3.1.0
- v3.0.1
- v3.0.0
- v2.1.0
- v2.0.1
- v2.0.0
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-fix/make-content-too-large-psr4-compliant
- dev-fix/validation-errors-as-indexed-array
- dev-feature/remove-resourceObject
- dev-development
- dev-feature/support-laravel-10
- dev-feature/create-jsonresourcehelper-trait
- dev-fix/remove-infinite-loop
- dev-feature/automates-resource-based-on-eloquent
- dev-fix/duplicate-includes-in-sub-includes
This package is auto-updated.
Last update: 2024-05-23 07:52:06 UTC
README
Make your Laravel API JSON:API compliant with the Brainstud\JsonApi
package.
Example usage
// 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); } }
Installation
Require the package
composer require brainstud/json-api-resource
Usage
- Let your resource object extend from
JsonApiResource
instead ofJsonResource
. - Implement a
register
method that returns the following array. The register has access to$this->resource
which contains the current model
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', ], ]; }
Relationships
JSON:API: Includes
For the relationships to be included they need to be loaded. This can be done by implementing a ?include
parameter or using spatie/laravel-query-builder.
Tweak response
The register
method doesn't have access to $request
like toArray
of JsonResource
has.
If you want to manipulate the response based on the request this can be done by overriding the addToResponse
method.
protected function addToResponse($request, $response): array { if ($this->requestWantsMeta($request, 'data') && ($data = $this->getData()) ) { $response['meta']['data'] = $data; } return $response; }
Resource depth
The resource depth has a default of 2. This can be changed by passing an array to the resource where the second item is the required resource depth. In the following example we use a depth of 3:
public function show(ShowCourseRequest $request, Course $course) { $query = (new CoursesQueryBuilder)->find($course->id); return new CourseResource([$query, 3]); }
Which allows us to ask for an include nested 3 levels deep: /courses/{identifier}?include=content,content.answers,content.answers.feedback
Exception handler
This package contains an exception handler to render exceptions as JSON:API error messages.
Either use this handler directly by editing your app.php
and registering this singleton
// app.php $app->singleton( Illuminate\Contracts\Debug\ExceptionHandler::class, \Brainstud\JsonApi\Handlers\JsonApiExceptionHandler::class );
Or register your own exception handler and delegate the render to the JsonApiExceptionHandler::render
method.
// 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); }
Return error response
There are multiple ways to return an error page
// 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);
License
JsonApi is open-sourced software licensed under the MIT Licence