gungcahyadipp / laravel-structured-response
Structured JSON API response package for Laravel
Package info
github.com/gungcahyadipp/Laravel-Structured-Response
pkg:composer/gungcahyadipp/laravel-structured-response
Requires
- php: ^8.2
- illuminate/contracts: ^10.0|^11.0|^12.0|^13.0
- illuminate/http: ^10.0|^11.0|^12.0|^13.0
- illuminate/pagination: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- larastan/larastan: ^2.0|^3.0
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- pestphp/pest: ^2.0|^3.0
- pestphp/pest-plugin-laravel: ^2.0|^3.0
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
README
Standar response JSON API untuk Laravel 10/11/12/13 dengan resource, relationship, pagination, includes, dan sparse fieldsets — tanpa dependensi yang tidak perlu.
Instalasi
composer require gungcahyadipp/laravel-structured-response
(Opsional) publish config:
php artisan vendor:publish --tag=structured-response-config
Quick start
use App\Http\Resources\UserResource; return ok(UserResource::make($user)); return ok(UserResource::collection(User::paginate(15))); return invalid($validator->errors()); return not_found('User not found');
Resource
use GungCahyadiPP\StructuredResponse\Http\Resources\JsonResource; class UserResource extends JsonResource { public function type(): string { return 'users'; } public function attributes(): array { return [ 'name' => $this->name, 'email' => $this->email, ]; } public function relationships(): array { return [ 'posts' => PostResource::collection($this->whenLoaded('posts')), ]; } }
Shorthand helpers
| Helper | Code | Use case |
|---|---|---|
ok($data, $message = '', $meta = []) |
200 | Success |
created($data, $message = '', $meta = []) |
201 | Resource created |
no_content() |
204 | Empty success |
error($message, $code = 500, $meta = []) |
* | Generic error |
invalid($errors, $message = 'Validation failed') |
422 | Validation |
not_found($message = 'Resource not found') |
404 | Missing resource |
unauthorized($message = 'Unauthenticated.') |
401 | Auth required |
forbidden($message = 'This action is unauthorized.') |
403 | Forbidden |
Fluent builder
return response_api() ->ok(UserResource::make($user)) ->withMeta(['generated_at' => now()->toISOString()]) ->send();
ResponseBuilder adalah immutable — setiap method mengembalikan instance baru.
Pagination
Cukup oper paginator (LengthAwarePaginator atau CursorPaginator). Meta pagination otomatis muncul di meta.pagination.
return ok(UserResource::collection(User::paginate(15)));
Includes
Mendukung ?include=posts.comments,company. Aktifkan via IncludeParser di config.
Sparse fieldsets
Mendukung ?fields[users]=name,email. Aktifkan via FieldsetParser di config.
Exception integration
Laravel 11+ (bootstrap/app.php):
->withExceptions(function (Exceptions $exceptions) { $exceptions->render( app(\GungCahyadiPP\StructuredResponse\Exceptions\ExceptionRenderer::class)->render(...) ); })
Laravel 10 (app/Exceptions/Handler.php):
public function render($request, Throwable $e) { $rendered = app(ExceptionRenderer::class)->render($request, $e); return $rendered ?? parent::render($request, $e); }
Testing helper
use GungCahyadiPP\StructuredResponse\Testing\AssertableJsonResponse; AssertableJsonResponse::from($response) ->assertResponseSuccess() ->assertResourceType('users') ->assertResourceCount(15) ->assertHasPagination();
Macros
use GungCahyadiPP\StructuredResponse\Support\ResponseBuilder; ResponseBuilder::macro('accepted', fn () => $this->ok(null, 'Accepted'));
Compatibility
| Laravel | PHP | Testbench |
|---|---|---|
| 10.x | 8.2 | ^8.0 |
| 11.x | 8.2 / 8.3 | ^9.0 |
| 12.x | 8.3 | ^10.0 |
| 13.x | 8.3 / 8.4 | ^11.0 |
Development
composer install vendor/bin/pest vendor/bin/phpstan analyse vendor/bin/php-cs-fixer check
License
MIT — see LICENSE.