Weave 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

Neomerx Json Api Laravel Package

laravel-json-api/neomerx-json-api

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require laravel-json-api/neomerx-json-api
    

    Add to composer.json:

    "autoload": {
        "psr-4": {
            "App\\JsonApi\\": "app/JsonApi/"
        }
    }
    

    Run composer dump-autoload.

  2. Basic Configuration Publish the config file:

    php artisan vendor:publish --provider="Neomerx\JsonApi\JsonApiServiceProvider" --tag="config"
    

    Update config/json-api.php with your API root (e.g., /api).

  3. First Use Case: Resource Definition Define a resource in app/JsonApi/Resources/UserResource.php:

    namespace App\JsonApi\Resources;
    
    use Neomerx\JsonApi\Resource\Resource;
    use Neomerx\JsonApi\Resource\ResourceCollection;
    use App\Models\User;
    
    class UserResource extends Resource
    {
        public static function fields(): array
        {
            return [
                'id',
                'name',
                'email',
                'posts' => function () {
                    return new PostResource();
                }
            ];
        }
    }
    
  4. First Controller

    use Neomerx\JsonApi\JsonApiResource;
    use App\JsonApi\Resources\UserResource;
    
    class UserController extends Controller
    {
        public function index()
        {
            $users = User::all();
            return JsonApiResource::collection(UserResource::class, $users);
        }
    }
    
  5. Route Definition

    use Illuminate\Support\Facades\Route;
    
    Route::jsonApiApi(['prefix' => 'api']);
    

Implementation Patterns

Resource Design Patterns

  1. Nested Resources Define relationships in fields():

    'posts' => function () {
        return new PostResource();
    }
    

    Use belongsTo, hasMany, etc., for eager loading:

    public static function relations(): array
    {
        return [
            'posts' => function () {
                return Post::query()->with('comments');
            }
        ];
    }
    
  2. Custom Field Transformations Use closures or methods:

    'full_name' => function (User $user) {
        return $user->first_name . ' ' . $user->last_name;
    }
    
  3. Pagination Use JsonApiResource::collection() with paginate():

    return JsonApiResource::collection(
        UserResource::class,
        User::paginate(10)
    );
    

Querying Patterns

  1. Filtering Use JsonApiResource::collection() with query parameters:

    $users = User::query()
        ->when(request('filter[name]', false), fn($q, $name) => $q->where('name', 'like', "%{$name}%"))
        ->get();
    
  2. Sorting Parse sort query param:

    $sort = request('sort', 'id');
    $users = User::query()->orderBy($sort)->get();
    
  3. Sparse Fieldsets Dynamically include/exclude fields:

    $fields = request('fields[user]', ['id', 'name']);
    $resource = new UserResource(User::find(1), $fields);
    

Integration with Laravel

  1. API Routes Use Route::jsonApiApi() for automatic route generation:

    Route::jsonApiApi(['prefix' => 'api', 'version' => 'v1']);
    
  2. Middleware Apply middleware to JSON API routes:

    Route::jsonApiApi(['middleware' => 'auth:api']);
    
  3. Form Requests Validate JSON API requests with JsonApiRequest:

    use Neomerx\JsonApi\JsonApiRequest;
    
    class StoreUserRequest extends FormRequest
    {
        public function authorize(): bool
        {
            return true;
        }
    
        public function rules(): array
        {
            return [
                'data' => 'required|array',
                'data.type' => 'required|string',
                'data.attributes' => 'sometimes|array',
            ];
        }
    }
    
  4. Documentation Use JsonApiResource::document() for meta/data:

    return JsonApiResource::document([
        'data' => UserResource::collection($users),
        'meta' => ['version' => '1.0']
    ]);
    

Gotchas and Tips

Common Pitfalls

  1. Case Sensitivity in Type Fields Ensure data.type matches the resource class name (e.g., User not user). Fix: Use Resource::type() to enforce consistency:

    class UserResource extends Resource
    {
        public static function type(): string
        {
            return 'users'; // lowercase plural
        }
    }
    
  2. Missing id in Resources JSON API requires id in every resource object. Fix: Ensure your model has a primary key ($primaryKey = 'id').

  3. Circular References Avoid infinite loops in nested resources:

    // ❌ Avoid
    'author' => function () { return new UserResource(); }
    
    // ✅ Fix: Use lazy loading
    'author' => function () { return new UserResource(); },
    public static function relations(): array
    {
        return ['author' => fn() => User::with('posts')->find($this->id)];
    }
    
  4. Pagination Headers JSON API requires pagination metadata. Use JsonApiResource::collection() with paginate():

    // ❌ Missing pagination headers
    return JsonApiResource::collection(UserResource::class, User::all());
    
    // ✅ Correct
    return JsonApiResource::collection(UserResource::class, User::paginate(10));
    

Debugging Tips

  1. Enable JSON API Debugging Add to config/json-api.php:

    'debug' => env('JSON_API_DEBUG', false),
    

    Logs will appear in storage/logs/laravel.json-api.log.

  2. Validate Requests Use JsonApiRequest to validate incoming data:

    $request = new JsonApiRequest();
    $request->replace(request()->all());
    if (!$request->isValid()) {
        return response()->json(['errors' => $request->errors()], 400);
    }
    
  3. Inspect Resource Output Use toArray() to debug resource serialization:

    $resource = new UserResource(User::find(1));
    dd($resource->toArray());
    

Extension Points

  1. Custom Error Handling Override JsonApiServiceProvider:

    public function register()
    {
        $this->app->singleton(JsonApiExceptionHandler::class, function () {
            return new CustomJsonApiExceptionHandler();
        });
    }
    
  2. Custom Serializers Extend Resource for custom logic:

    class CustomUserResource extends UserResource
    {
        public function toArray($request = null)
        {
            $array = parent::toArray($request);
            $array['attributes']['custom_field'] = 'value';
            return $array;
        }
    }
    
  3. Middleware for JSON API Add to app/Http/Kernel.php:

    protected $middlewareGroups = [
        'json-api' => [
            \Neomerx\JsonApi\JsonApiMiddleware::class,
            // Other middleware...
        ],
    ];
    
  4. Testing Use JsonApiTestCase for assertions:

    use Neomerx\JsonApi\Testing\JsonApiTestCase;
    
    class UserTest extends JsonApiTestCase
    {
        public function test_user_serialization()
        {
            $response = $this->getJson('/api/users/1');
            $response->assertJsonApiResource(UserResource::class);
        }
    }
    
  5. Performance Optimization

    • Eager Loading: Use with() in relations() to avoid N+1 queries.
    • Caching: Cache serialized resources:
      $resource = Cache::remember("user.{$user->id}", now()->addHours(1), function () use ($user) {
          return new UserResource($user);
      });
      
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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table