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

Laravel Apiable Laravel Package

open-southeners/laravel-apiable

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation:

    composer require open-southeners/laravel-apiable
    php artisan apiable:install
    

    The apiable:install command publishes the config file and creates a default ApiableServiceProvider.

  2. Initial Setup:

    • Review the published config at config/apiable.php (e.g., default namespace, JSON:API version).
    • Register the provider in config/app.php under providers:
      OpenSoutheners\Apiable\ApiableServiceProvider::class,
      
  3. First Use Case: Create a JSON:API resource for a Post model:

    php artisan make:apiable Post
    

    This generates:

    • app/Http/Resources/PostResource.php (default JSON:API resource).
    • app/Http/Resources/PostCollection.php (for paginated responses).

    Use it in a controller:

    use OpenSoutheners\Apiable\Http\Resources\PostResource;
    
    public function show(Post $post)
    {
        return new PostResource($post);
    }
    
  4. Key Files to Review:

    • config/apiable.php: Global settings (e.g., api_version, default_namespace).
    • app/Http/Resources/: Auto-generated resource classes.
    • app/Providers/ApiableServiceProvider.php: Custom logic (e.g., global resource macros).

Implementation Patterns

Core Workflows

  1. Resource Creation:

    • Use make:apiable for models or manually extend OpenSoutheners\Apiable\Http\Resources\JsonApiResource.
    • Example custom resource:
      namespace App\Http\Resources;
      
      use OpenSoutheners\Apiable\Http\Resources\JsonApiResource;
      
      class CustomPostResource extends JsonApiResource
      {
          public function toArray($request)
          {
              return [
                  'id' => $this->id,
                  'title' => $this->title,
                  'custom_field' => $this->customField, // Override default fields
              ];
          }
      }
      
  2. Relationships:

    • Define relationships in the resource:
      public function toArray($request)
      {
          return [
              'id' => $this->id,
              'author' => new UserResource($this->whenLoaded('author')),
          ];
      }
      
    • Use whenLoaded() to avoid N+1 queries.
  3. Collections:

    • Extend JsonApiResourceCollection for paginated responses:
      namespace App\Http\Resources;
      
      use OpenSoutheners\Apiable\Http\Resources\JsonApiResourceCollection;
      
      class PostCollection extends JsonApiResourceCollection
      {
          public function toArray($request)
          {
              return [
                  'data' => $this->collection,
                  'meta' => ['total' => $this->collection->total()],
              ];
          }
      }
      
  4. API Versioning:

    • Configure in config/apiable.php:
      'api_version' => 'v1',
      
    • Use middleware to enforce versioning (e.g., ApiableVersionMiddleware).
  5. Request Handling:

    • Access request data in resources:
      public function toArray($request)
      {
          $include = $request->input('include', []);
          return [...];
      }
      
  6. Macros and Extensions:

    • Register global macros in ApiableServiceProvider:
      \OpenSoutheners\Apiable\Http\Resources\JsonApiResource::macro('addMeta', function ($key, $value) {
          $this->additional['meta'][$key] = $value;
          return $this;
      });
      
    • Use in resources:
      return (new PostResource($post))->addMeta('status', 'published');
      
  7. Error Handling:

    • Customize error responses via ApiableServiceProvider:
      \OpenSoutheners\Apiable\Exceptions\Handler::render($request, throwable: $exception);
      

Gotchas and Tips

Common Pitfalls

  1. Namespace Conflicts:

    • Ensure default_namespace in config/apiable.php matches your app/Http/Resources path.
    • Example: 'default_namespace' => 'App\Http\Resources'.
  2. Relationship Loading:

    • Avoid eager-loading all relationships by default. Use with() in queries or whenLoaded() in resources:
      // Bad: Loads all relationships unconditionally
      $posts = Post::with('author', 'comments')->get();
      
      // Good: Load only requested relationships
      $posts = Post::query();
      if ($request->has('include')) {
          $posts->with(explode(',', $request->input('include')));
      }
      
  3. Pagination Meta:

    • Default pagination meta (e.g., links, meta) may not match your API design. Override in PostCollection:
      public function toArray($request)
      {
          return [
              'data' => $this->collection,
              'links' => [], // Customize or remove
              'meta' => ['custom_meta' => 'value'],
          ];
      }
      
  4. Caching Resources:

    • Resources are not cached by default. For performance, implement caching in toArray():
      public function toArray($request)
      {
          return Cache::remember("post.{$this->id}", now()->addMinutes(10), function () {
              return [
                  'id' => $this->id,
                  'title' => $this->title,
              ];
          });
      }
      
  5. Middleware Order:

    • Ensure ApiableVersionMiddleware runs before ApiableMiddleware in app/Http/Kernel.php:
      protected $middleware = [
          \OpenSoutheners\Apiable\Http\Middleware\ApiableVersionMiddleware::class,
          \OpenSoutheners\Apiable\Http\Middleware\ApiableMiddleware::class,
      ];
      
  6. Testing:

    • Use JsonApiTestCase for assertions:
      use OpenSoutheners\Apiable\Testing\JsonApiTestCase;
      
      class PostTest extends JsonApiTestCase
      {
          public function test_post_show()
          {
              $response = $this->getJson('/api/v1/posts/1');
              $response->assertJsonApiResource('posts');
          }
      }
      

Debugging Tips

  1. Enable JSON:API Debugging:

    • Set 'debug' => true in config/apiable.php to log resource processing.
  2. Check Resource Output:

    • Use dd($resource->resolve($request)) to inspect raw resource data before serialization.
  3. Validate Requests:

    • Ensure Accept: application/vnd.api+json header is present. Add middleware to enforce:
      $request->headers->set('Accept', 'application/vnd.api+json');
      
  4. Common Errors:

    • Class not found: Verify the resource class exists and namespace is correct.
    • Method not allowed: Ensure routes use ApiableRouteMiddleware.
    • Missing data key: Confirm the resource extends JsonApiResource and returns an array.

Extension Points

  1. Custom Serializers:

    • Override serializeRelationship() for custom relationship handling:
      protected function serializeRelationship($name, $value, $request)
      {
          if ($name === 'author') {
              return new UserResource($value);
          }
          return parent::serializeRelationship($name, $value, $request);
      }
      
  2. Dynamic Attributes:

    • Use mergeWhen() to conditionally add fields:
      public function toArray($request)
      {
          return $this->mergeWhen(
              $request->user()->can('view_hidden'),
              ['hidden_field' => $this->hiddenField]
          );
      }
      
  3. API Documentation:

    • Integrate with tools like Postman or Swagger by extending the resource to include OpenAPI annotations:
      /**
       * @OA\Get(
       *     path="/api/v1/posts/{id}",
       *     @OA\Response(response="200", description="Returns a post")
       * )
       */
      
  4. GraphQL-like Includes:

    • Parse include parameter to load nested relationships dynamically:
      public function toArray($request)
      {
          $includes = explode(',', $request->input('include', ''));
          if (in_array('author', $includes)) {
              $this->load('author');
          }
          return [...];
      }
      
  5. Custom Headers:

    • Add headers to responses via withResponse():
      return (new PostResource($post))
          ->withResponse($request, function ($response) {
              $response->header('X-Custom-Header', 'value');
          });
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope