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

Php Api Descriptions Laravel Package

kleijnweb/php-api-descriptions

Parse and handle PHP API Description documents (OpenAPI-like) with utilities for loading, validating, and working with structured API metadata. Useful for tooling that needs to read API specs and generate clients, docs, or integrations.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require kleijnweb/php-api-descriptions
    

    Ensure your project uses PHP 8.0+ (recommended) and Laravel 8+.

  2. First Use Case: Defining an API Contract Create a Contract class (e.g., app/Contracts/UserContract.php):

    use Kleijnweb\ApiDescriptions\Contract;
    
    class UserContract extends Contract
    {
        public function getDescription(): string
        {
            return 'API for user management';
        }
    
        public function getEndpoints(): array
        {
            return [
                'GET /users' => $this->getUsers(),
                'POST /users' => $this->createUser(),
            ];
        }
    
        public function getUsers(): string
        {
            return 'Returns a list of users';
        }
    
        public function createUser(): string
        {
            return 'Creates a new user';
        }
    }
    
  3. Generating Documentation Use the ApiDescriptions facade to generate OpenAPI/Swagger docs:

    use Kleijnweb\ApiDescriptions\Facades\ApiDescriptions;
    
    $contract = new UserContract();
    $description = ApiDescriptions::describe($contract);
    
  4. Viewing Output Output the description as JSON or YAML:

    $json = $description->toJson();
    $yaml = $description->toYaml();
    

Implementation Patterns

Contract-First Workflow

  1. Define Contracts Early Create contracts before implementing endpoints. Example:

    class OrderContract extends Contract
    {
        public function getEndpoints(): array
        {
            return [
                'GET /orders/{id}' => $this->getOrder(),
                'POST /orders' => $this->createOrder(),
            ];
        }
    
        public function getOrder(): string
        {
            return 'Returns an order by ID';
        }
    
        public function createOrder(): array
        {
            return [
                'description' => 'Creates an order',
                'requestBody' => [
                    'content' => [
                        'application/json' => [
                            'schema' => [
                                'type' => 'object',
                                'properties' => [
                                    'product_id' => ['type' => 'integer'],
                                    'quantity' => ['type' => 'integer'],
                                ],
                            ],
                        ],
                    ],
                ],
            ];
        }
    }
    
  2. Integrate with Laravel Routes Use contracts to validate routes dynamically:

    Route::get('/users', function () {
        $contract = new UserContract();
        $description = ApiDescriptions::describe($contract);
        // Use $description to validate requests or generate docs
    });
    
  3. Group Contracts by Module Organize contracts by feature (e.g., app/Contracts/Auth/, app/Contracts/Ecommerce/). Merge them in a central ApiContract:

    class ApiContract extends Contract
    {
        public function getEndpoints(): array
        {
            return array_merge(
                (new AuthContract())->getEndpoints(),
                (new EcommerceContract())->getEndpoints()
            );
        }
    }
    
  4. Generate API Docs Automatically Create a Laravel command to dump OpenAPI specs:

    use Kleijnweb\ApiDescriptions\Facades\ApiDescriptions;
    use Illuminate\Console\Command;
    
    class GenerateApiDocs extends Command
    {
        protected $signature = 'api:docs';
        protected $description = 'Generate OpenAPI documentation';
    
        public function handle()
        {
            $contract = new ApiContract();
            $description = ApiDescriptions::describe($contract);
            file_put_contents(public_path('api-docs.yaml'), $description->toYaml());
            $this->info('API docs generated!');
        }
    }
    

Advanced Patterns

  1. Dynamic Endpoint Descriptions Use closures for dynamic descriptions:

    public function getEndpoints(): array
    {
        return [
            'GET /products' => fn() => 'Returns ' . config('app.env') . ' products',
        ];
    }
    
  2. Reuse Descriptions Extend contracts to share common endpoints:

    class BaseContract extends Contract
    {
        protected function healthCheck(): string
        {
            return 'Returns API health status';
        }
    }
    
    class AdminContract extends BaseContract
    {
        public function getEndpoints(): array
        {
            return [
                'GET /health' => $this->healthCheck(),
            ];
        }
    }
    
  3. Integrate with Laravel Validation Use contract descriptions to validate requests:

    use Kleijnweb\ApiDescriptions\Description;
    
    Route::post('/users', function (Request $request) {
        $contract = new UserContract();
        $description = ApiDescriptions::describe($contract);
        $endpoint = $description->getEndpoint('POST /users');
    
        if ($endpoint['requestBody']) {
            $validator = Validator::make($request->all(), $endpoint['requestBody']['content']['application/json']['schema']['properties']);
            if ($validator->fails()) {
                return response()->json(['errors' => $validator->errors()], 422);
            }
        }
    });
    

Gotchas and Tips

Common Pitfalls

  1. Archived Package

    • The package is archived, so expect no new updates. Use with caution in production.
    • Consider forking or migrating to alternatives like zircote/swagger-php if long-term maintenance is critical.
  2. Limited OpenAPI Support

    • The package generates basic OpenAPI descriptions. For advanced features (e.g., security schemes, servers), manually extend the Description class:
      $description->setServers(['https://api.example.com']);
      $description->addSecurityScheme('api_key', ['type' => 'apiKey', 'in' => 'header']);
      
  3. No Built-in Route Registration

    • Contracts are descriptive only; they don’t auto-register routes. Use them alongside Laravel’s routing:
      // ❌ Won't work (contracts don't auto-register)
      // $contract->getEndpoints();
      
      // ✅ Correct: Manually map routes
      Route::get('/users', [UserController::class, 'index']);
      
  4. Performance with Large APIs

    • Generating descriptions for thousands of endpoints can be slow. Cache results:
      $description = Cache::remember('api-docs', now()->addHours(1), function () {
          return ApiDescriptions::describe(new ApiContract());
      });
      

Debugging Tips

  1. Validate Descriptions Use the toArray() method to inspect raw data:

    $description = ApiDescriptions::describe(new UserContract());
    dd($description->toArray());
    
  2. Handle Missing Endpoints If an endpoint is missing, the package throws a RuntimeException. Catch it gracefully:

    try {
        $endpoint = $description->getEndpoint('GET /nonexistent');
    } catch (\RuntimeException $e) {
        Log::warning('Missing endpoint: ' . $e->getMessage());
    }
    
  3. Extend Description Class Override methods in a custom class for additional fields:

    class CustomDescription extends \Kleijnweb\ApiDescriptions\Description
    {
        public function addCustomField(string $key, $value): self
        {
            $this->data['x-' . $key] = $value;
            return $this;
        }
    }
    

Configuration Quirks

  1. No Built-in Config File The package has no default config. Initialize it manually:

    ApiDescriptions::setTitle('My API')
                    ->setVersion('1.0.0')
                    ->setDescription('API for my Laravel app');
    
  2. YAML Output Formatting The toYaml() method uses basic formatting. For pretty-printing, use a library like spatie/fork:

    use Spatie\ArrayToXml\ArrayToXml;
    
    $yaml = ArrayToXml::convertToYaml($description->toArray(), [], true);
    
  3. PHP 8.0+ Features The package leverages named arguments and union types. Ensure your PHP version supports them:

    // Works in PHP 8.0+
    public function getEndpoints(): array
    {
        return [
            'GET /users' => $this->getUsers(description: 'List all users'),
        ];
    }
    

Extension Points

  1. Custom Description Formats Extend the Description class to support new formats (e.g., Markdown):

    class MarkdownDescription extends \Kleijnweb\ApiDescriptions\Description
    {
        public function toMarkdown(): string
        {
            return "# API Description\n\n" . $this->data['description'];
        }
    }
    
  2. **Integrate with API Gate

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.
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
spatie/mailcoach-vapor