Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jsonapi Bundle Laravel Package

paknahad/jsonapi-bundle

Laravel package for building JSON:API-compliant APIs. Provides controllers, resources and request handling to standardize responses, filtering, sorting, pagination, includes and errors, helping you ship consistent endpoints faster.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require paknahad/jsonapi-bundle
    

    Add to config/app.php under providers:

    Paknahad\JsonApiBundle\Providers\JsonApiServiceProvider::class,
    

    Publish the config (optional):

    php artisan vendor:publish --provider="Paknahad\JsonApiBundle\Providers\JsonApiServiceProvider" --tag=config
    
  2. Basic API Endpoint Define a resource in routes/api.php:

    Route::get('/posts', [JsonApiController::class, 'index'])->name('posts.index');
    
  3. Define a Resource Create a resource class (e.g., app/Http/Resources/PostResource.php):

    namespace App\Http\Resources;
    
    use Paknahad\JsonApiBundle\Resources\Resource;
    
    class PostResource extends Resource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'title' => $this->title,
                'body' => $this->body,
            ];
        }
    }
    
  4. Controller Integration Use the JsonApiController trait or extend JsonApiController:

    use Paknahad\JsonApiBundle\Http\Controllers\JsonApiController;
    
    class PostController extends JsonApiController
    {
        public function index()
        {
            $posts = Post::all();
            return $this->respondWithResourceCollection(PostResource::class, $posts);
        }
    }
    

Implementation Patterns

1. Resource Design

  • Single Resource
    return $this->respondWithResource(PostResource::class, $post);
    
  • Collection
    return $this->respondWithResourceCollection(PostResource::class, $posts);
    
  • Nested Resources
    class PostResource extends Resource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'title' => $this->title,
                'comments' => CommentResource::collection($this->comments),
            ];
        }
    }
    

2. Relationships

  • Explicit Relationships
    return $this->respondWithRelationships(PostResource::class, $post, ['comments']);
    
  • Lazy Loading
    class PostResource extends Resource
    {
        public function relationships()
        {
            return [
                'comments' => function () {
                    return $this->comments()->with('author');
                },
            ];
        }
    }
    

3. Filtering, Sorting, Pagination

  • Query Builder Integration
    $query = Post::query();
    if ($request->has('filter[title]')) {
        $query->where('title', 'like', '%' . $request->input('filter[title]') . '%');
    }
    return $this->respondWithResourceCollection(PostResource::class, $query->paginate());
    

4. Customizing JSON:API Output

  • Meta Data
    return $this->respondWithResourceCollection(
        PostResource::class,
        $posts,
        ['meta' => ['total' => $posts->total()]]
    );
    
  • Includes (Sparse Fieldsets)
    return $this->respondWithResourceCollection(
        PostResource::class,
        $posts,
        null,
        ['include' => 'comments.author']
    );
    

5. API Versioning

  • Route-Based Versioning
    Route::prefix('v1')->group(function () {
        Route::get('/posts', [PostController::class, 'index']);
    });
    
  • Resource Versioning
    class PostResource extends Resource
    {
        public function version()
        {
            return 'v1';
        }
    }
    

Gotchas and Tips

1. Common Pitfalls

  • Missing id Field JSON:API requires id in every resource. Ensure your toArray() includes it:
    return ['id' => $this->id, ...];
    
  • Incorrect Relationship URLs If relationships fail to link, verify relationships() or toArray() includes proper links:
    public function links()
    {
        return [
            'self' => route('posts.show', $this->id),
            'related' => route('comments.index', $this->id),
        ];
    }
    
  • Pagination Conflicts Use JsonApiPaginator for consistent pagination:
    use Paknahad\JsonApiBundle\Pagination\JsonApiPaginator;
    return JsonApiPaginator::make($posts, $posts->perPage());
    

2. Debugging

  • Enable JSON:API Debugging Set JSONAPI_DEBUG in .env:
    JSONAPI_DEBUG=true
    
    This logs validation errors and schema mismatches.
  • Check for Deprecated Methods The bundle evolves; refer to CHANGELOG.md for breaking changes (e.g., respond()respondWithResource()).

3. Performance Tips

  • Eager Load Relationships Avoid N+1 queries:
    $posts = Post::with('comments.author')->get();
    
  • Cache Resource Classes Laravel’s OPcache will handle this, but for heavy APIs, consider compiling resources:
    php artisan jsonapi:compile
    

4. Extension Points

  • Custom Serializers Extend Paknahad\JsonApiBundle\Serializers\Serializer for non-standard data types (e.g., dates):
    class CustomDateSerializer extends Serializer
    {
        public function serialize($data)
        {
            return Carbon::parse($data)->toIso8601String();
        }
    }
    
  • Middleware for Auth/Validation Use Laravel’s middleware to enforce JSON:API rules:
    Route::middleware(['jsonapi.validate'])->group(function () {
        // Routes here
    });
    

5. Configuration Quirks

  • Default Meta Fields Override in config/jsonapi.php:
    'meta' => [
        'default' => ['version' => '1.0'],
    ],
    
  • Disable Strict Mode If you need flexibility with JSON:API spec:
    'strict' => env('JSONAPI_STRICT', false),
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky