brainstud / json-api-resource
Build JSON:API compliant Laravel API resources
Installs: 3 297
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 2
Requires
- php: ^8.2
- laravel/framework: ^8.0 || ^9.0 || ^10.0 || ^11.0
Requires (Dev)
- laravel/pint: ^1.17
- orchestra/testbench: ^7.22.0
- phpunit/phpunit: ^9.6.3
- dev-main
- v4.2.0
- v4.1.1
- v4.1.0
- v4.0.6
- v4.0.5
- v4.0.4
- v4.0.3
- 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/improve-toId-docblock
- dev-fix/id-resolving
- dev-chore/update-documentation
- 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-10-16 07:48:35 UTC
README
Make your Laravel API JSON:API compliant with the Brainstud\JsonApi
package.
Table of contents
- Installation
- Usage
- Relationships
- Resource depth
- Exception handler
- Example
- Deprecated
register
method - Tweaking responses
- License
Installation
Require the package
composer require brainstud/json-api-resource
Usage
- Let your resource object extend from
JsonApiResource
instead ofJsonResource
. - Set the type of your resource as a string in
$this->type
. - For each part of your resource, define the matching
to{resourcePart}
method.
class Resource extends JsonApiResource { protected string $type = 'resources'; protected function toAttributes(Request $request): array { return [ 'field' => $this->resource->field, 'other_field' => $this->resource->other_field, ]; } protected function toRelationships(Request $request): array { return [ 'relation' => ['relationMethod', Relation::class], ]; } protected function toLinks(Request $request): array { return [ 'type_of_link' => ['href' => 'link'], ]; } protected function toMeta(Request $request): array { return [ 'meta' => 'data', ]; } }
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.
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);
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 string $type = 'courses'; protected function toAttributes(Request $request): array { return [ 'title' => $this->resource->title, 'description' => $this->resource->description, 'created_at' => $this->resource->created_at->format('c'), ]; } protected function toRelationships(Request $request): array { return [ 'enrollments' => ['enrollments', EnrollmentResourceCollection::class], ]; } protected function toLinks(Request $request): array { return [ 'view' => ['href' => $this->resource->getShowUrl()], ]; } protected function toMeta(Request $request): array { return [ 'enrollments' => $this->resource->enrollments->count(), ]; } } // 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); } }
Defining resources via the register
method
In the previous version of the package, you would have to define the resource structure via a register method. This is still possible, but it is deprecated and will be removed in a later version.
To use this way of defining a resource, simply define a register
method in your 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', ], 'links' => [ 'some_key' => 'some link', ], ]; }
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; }
License
JsonApi is open-sourced software licensed under the MIT Licence