Filament Api Service

repository·main·Indexed 42 days ago

https://github.com/rupadana/filament-api-service

A package for FilamentPHP that automates the generation of RESTful API endpoints for Filament resources. It provides built-in support for authentication, authorization, filtering, sorting, and multi-tenancy, and integrates with Scramble for automatic OpenAPI documentation.

Tokens
9.7K
Snippets
35
Records
45
Agent score
52%

What's inside Filament Api Service

  1. Configure Multi-Tenancy for APIs

    main

    Enable tenant-aware API responses to ensure users only retrieve data belonging to their authorized tenants.

    • Enable Tenancy: Set tenancy.enabled to true in the config. This automatically scopes queries to the user's tenants.
    • Tenant Awareness (URI Prefix): Set tenancy.awareness to true. This adds a {tenant} prefix to your API routes (e.g., api/admin/{tenant}/blog).
    • Override Scoping: In a specific Resource, set protected static bool $isScopedToTenant = false; to return all records regardless of tenancy.
    • Custom Relationship: In a Handler, override protected static ?string $tenantOwnershipRelationshipName = null; to change the relationship used for scoping.
    // Example of tenant-aware route structure when awareness is enabled:
    // POST api/admin/{tenant}/blog
    // GET  api/admin/{tenant}/blog/{id}
  2. Generate an API service for a Filament resource

    main

    Use the Artisan command to automatically generate RESTful API endpoints for an existing Filament resource. By default, routes are prefixed with your panel ID (e.g., /api/admin/blogs).

    Available endpoints generated:

    • GET /api/{panel_id}/{resource}: Returns a LengthAwarePaginator.
    • GET /api/{panel_id}/{resource}/{id}: Returns a single resource.
    • PUT /api/{panel_id}/{resource}/{id}: Updates a resource.
    • POST /api/{panel_id}/{resource}: Creates a resource.
    • DELETE /api/{panel_id}/{resource}/{id}: Deletes a resource.
    php artisan make:filament-api-service BlogResource
  3. Secure your API with Authentication

    main

    The package provides built-in authentication routes:

    • POST /api/auth/login
    • POST /api/auth/logout

    It integrates with spatie/laravel-permission and filament-shield. By default, it uses the permission middleware. If you wish to use a different middleware setup, set use-spatie-permission-middleware to false in the config.

  4. Enable filtering and sorting in API queries

    main

    The package uses spatie/laravel-query-builder for dynamic filtering, sorting, and field selection. To allow these operations on your models, implement the following contracts in your Model class:

    • HasAllowedFields: Controls which database fields can be selected via the query string.
    • HasAllowedSorts: Controls which fields can be used for sorting.
    • HasAllowedFilters: Controls which fields can be used for filtering.
    use Rupadana\\ApiService\\Contracts\\HasAllowedFields;
    use Rupadana\\ApiService\\Contracts\\HasAllowedSorts;
    use Rupadana\\ApiService\\Contracts\\HasAllowedFilters;
    
    class User extends Model implements HasAllowedFields, HasAllowedSorts, HasAllowedFilters {
        public static function getAllowedFields(): array
        {
            return ['name', 'email'];
        }
    
        public static function getAllowedSorts(): array
        {
            return ['created_at'];
        }
    
        public static function getAllowedFilters(): array
        {
            return ['email'];
        }
    }
  5. Install Filament Api Service

    main

    To use Filament Api Service, install it via Composer and register the plugin in your Filament Panel Provider.

    Note for Laravel 11 users: You must run php artisan install:api to publish the personal_access_tokens migration, then run php artisan migrate.

    # Install the package
    composer require rupadana/filament-api-service
    // Register in your Filament Provider
    use Rupadana\
    ApiService\[ApiServicePlugin\;
    
    $panel->plugins([
        ApiServicePlugin::make()
    ]);
  6. Create and use API Handlers

    main

    Handlers manage the logic for specific API actions. You can generate specific handlers (Create, Update, Delete, Detail, Pagination) using the Artisan command.

    To customize the logic of a generated handler, you can export the stubs to your application and edit them directly.

    # Generate a handler for a resource
    php artisan make:filament-api-handler BlogResource
    
    # Export handler stubs for customization
    php artisan vendor:publish --tag=api-service-stubs
  7. Create API services for Resources in Clusters

    main

    While the package supports auto-discovery of API services in clusters (since v4.0.1), creating new services for clustered resources requires manual directory structure setup.

    If your resource is at App\Filament\Clusters\Catalog\Resources\ProductResource, you must manually create the following structure:

    app/Filament/Clusters/Catalog/Resources/
    └── Products/
        ├── ProductResource.php
        ├── Api/
        │   ├── ProductApiService.php
        │   ├── Transformers/
        │   │   └── ProductTransformer.php
        │   └── Handlers/
        │       ├── CreateHandler.php
        │       ├── UpdateHandler.php
        │       ├── DeleteHandler.php
        │       ├── DetailHandler.php
        │       └── PaginationHandler.php

    Tip: The easiest way to implement this is to copy the structure from tests/Fixtures/Resources/Product/Api/ and adapt the namespaces.

  8. Workaround for Scramble API Documentation limitations

    main

    Scramble may not automatically detect filter/sort options or custom transformer structures.

    To document filters and sorts manually, add PHPDoc annotations to your handlers:

    /**
     * Get paginated list of products
     * 
     * @queryParam filter[name] Filter by product name
     * @queryParam sort Sort by field (e.g., name, created_at)
     * @queryParam fields[products] Select specific fields (e.g., id,name,price)
     */
    public function handler(): JsonResponse
    {
        // ...
    }
    /**
     * Get paginated list of products
     * 
     * @queryParam filter[name] Filter by product name
     * @queryParam sort Sort by field (e.g., name, created_at)
     * @queryParam fields[products] Select specific fields (e.g., id,name,price)
     */
    public function handler(): JsonResponse
    {
        // Your handler logic
    }
  9. Customize or Extend Package Resources

    main

    Package resources like TokenResource are not published by default. Instead, use configuration or inheritance to customize them.

    1. Configure via config/api-service.php

    You can change the navigation group, icon, and visibility:

    'navigation' => [
        'token' => [
            'cluster' => null,
            'group' => 'User',
            'sort' => -1,
            'icon' => 'heroicon-o-key',
            'should_register_navigation' => false,
        ],
    ],

    2. Extend the Resource

    To override methods (like getNavigationIcon), create a custom resource that extends the base package resource:

    namespace App\Filament\Resources;
    
    use Rupadana\ApiService\Resources\TokenResource as BaseTokenResource;
    
    class CustomTokenResource extends BaseTokenResource
    {
        public static function getNavigationIcon(): ?string
        {
            return 'heroicon-o-lock-closed';
        }
    }

    Then, register your CustomTokenResource in your panel provider instead of the default one.

  10. Integrate with FilamentShield

    main

    The package uses Spatie's permission middleware by default. If you receive "User does not have the right permissions" errors:

    1. Setup Shield: Run php artisan shield:setup --fresh and php artisan shield:install.
    2. Generate Permissions: Run php artisan shield:generate --all to create permissions for your API handlers (e.g., view_blog, create_blog).
    3. Assign Roles: Use the Filament Shield UI to assign these new permissions to your roles.

    To disable permission middleware entirely, update config/api-service.php:

    return [
        'use-spatie-permission-middleware' => false,
    ];
  11. Transform API responses

    main

    To customize the JSON structure returned by your API, use Transformers.

    1. Generate a transformer using php artisan make:filament-api-transformer {Resource}.
    2. Implement the toArray($request) method in the generated class.
    3. Register the transformer in your Filament Resource by overriding getApiTransformer().
    // 1. Generate
    // php artisan make:filament-api-transformer Blog
    
    // 2. Implement (App\Filament\Resources\BlogResource\Api\Transformers\BlogTransformer)
    class BlogTransformer extends JsonResource
    {
        public function toArray($request)
        {
            return $this->resource->toArray();
        }
    }
    
    // 3. Register in your Resource
    class BlogResource extends Resource
    {
        public static function getApiTransformer()
        {
            return BlogTransformer::class;
        }
    }
  12. Access API from Desktop Applications

    main

    If desktop applications are being redirected to login instead of accessing the API, check the following:

    1. Middleware: Ensure routes use auth:sanctum (the package default). Verify in config/api-service.php:
      'logout-middleware' => ['auth:sanctum'],
    2. CORS: If the app is on a different domain, update config/cors.php:
      'paths' => ['api/*', 'sanctum/csrf-cookie'],
      'allowed_origins' => ['*'], // Or your specific domain
      'supports_credentials' => true,
    3. Authentication: Desktop apps must use token-based authentication by sending the header: Authorization: Bearer {your-token}
    4. Session: Ensure you are not using session-based authentication for API routes; use Sanctum tokens.