puchan/laravel-api-docs

Automatic API documentation generator for Laravel applications

Installs: 81

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/puchan/laravel-api-docs

1.1.1 2025-10-25 02:40 UTC

This package is auto-updated.

Last update: 2025-12-25 03:12:11 UTC


README

Latest Version on Packagist Total Downloads License

Automatic API documentation generator for Laravel applications. Generate beautiful, interactive API documentation by simply installing the package - zero configuration required!

✨ Features

  • Zero Configuration - Works immediately after installation
  • Auto Route Scanning - Automatically discovers all your API routes
  • Database Schema Integration - Shows available fields from database tables with toggle option
  • Advanced Parameter Detection - Auto-detects query params from:
    • FormRequests validation rules
    • Method signatures and type hints
    • Controller method body ($request->has(), $request->input(), etc.)
    • Pagination patterns
  • Real Data Examples - Fetches actual data from database for response examples with security sanitization
  • Smart Response Detection - Detects custom response patterns:
    • Resource::collection() for arrays
    • new Resource() for single objects
    • sendResponse() custom methods
  • Laravel Resource Support - Uses your Resource classes for accurate response examples
  • Multiple Formats - HTML, JSON, and OpenAPI/Swagger formats
  • Compact UI - Space-efficient table format with optimized spacing and typography
  • URL Persistence - Bookmarkable URLs with controller selection state
  • Pagination Detection - Automatically identifies paginated endpoints
  • Highly Configurable - Customize everything via config file and environment variables

📋 Requirements

  • PHP 8.1 or higher
  • Laravel 10.x, 11.x, or 12.x
  • PostgreSQL (for database schema reading)

📦 Installation

Install the package via Composer:

composer require puchan/laravel-api-docs

The package will be auto-discovered by Laravel. No additional setup required!

🚀 Quick Start

After installation, your API documentation is immediately available at:

http://your-app.test/api-docs

That's it! The package automatically:

  • Scans all your API routes
  • Reads database schemas (PostgreSQL)
  • Detects query parameters from FormRequests AND controller code
  • Fetches real data from database for response examples
  • Detects Resource::collection() vs single Resources
  • Generates response examples with security sanitization
  • Creates beautiful, compact documentation with URL persistence

📖 Available Endpoints

1. HTML Documentation (Interactive UI)

GET /api-docs

Beautiful, responsive web interface with:

  • Collapsible route sections
  • Color-coded HTTP methods
  • Compact parameter tables
  • Database field information (toggleable)
  • Real data examples with security sanitization
  • URL persistence for bookmarking
  • One-click cURL and Postman export
  • Syntax-highlighted JSON examples
  • Optimized spacing for maximum content visibility

2. JSON Format (Programmatic Access)

GET /api-docs/json

Complete API documentation in JSON format for:

  • Custom documentation tools
  • CI/CD integration
  • API testing tools

3. OpenAPI/Swagger Format

GET /api-docs/swagger

OpenAPI 3.0 compliant format for:

  • Swagger UI
  • Postman import
  • API clients generation

⚙️ Configuration

Publishing Config (Optional)

While the package works without configuration, you can customize it:

php artisan vendor:publish --tag=api-docs-config

This creates config/api-docs.php:

<?php

return [
    // API Documentation Title
    'title' => env('API_DOCS_TITLE', config('app.name') . ' API Documentation'),

    // API Version
    'version' => env('API_DOCS_VERSION', '1.0.0'),

    // API Base URL
    'base_url' => env('API_DOCS_BASE_URL', config('app.url') . '/api'),

    // Enable/disable documentation routes
    'enabled' => env('API_DOCS_ENABLED', true),

    // Route prefix for documentation
    'route_prefix' => env('API_DOCS_ROUTE_PREFIX', 'api-docs'),

    // Middleware to apply to documentation routes
    'middleware' => ['web'],

    // Route Filters
    'route_filters' => [
        // Only include routes starting with these prefixes
        'include_prefixes' => ['api/'],

        // Exclude routes matching these patterns
        'exclude_patterns' => [
            'sanctum/*',
            'telescope/*',
            'horizon/*',
        ],
    ],

    // Resource Detection
    'resources' => [
        // Automatically detect and use Laravel Resources
        'auto_detect' => true,

        // Namespace where resources are located
        'namespace' => 'App\\Http\\Resources',
    ],

    // Database Schema
    'database' => [
        // Schema name for PostgreSQL
        'schema' => 'public',

        // Show database schema in documentation
        // Set to false to hide database schema tab (useful in production)
        'show_in_docs' => env('API_DOCS_SHOW_DATABASE_SCHEMA', true),

        // Use actual data from database for response examples
        // Set to false to use generated dummy data instead
        'use_actual_data' => env('API_DOCS_USE_ACTUAL_DATA', true),
    ],
];

Environment Variables

Configure via .env file:

API_DOCS_ENABLED=true
API_DOCS_TITLE="My Awesome API"
API_DOCS_VERSION="2.0.0"
API_DOCS_BASE_URL="https://api.example.com"
API_DOCS_ROUTE_PREFIX="docs"
API_DOCS_SHOW_DATABASE_SCHEMA=true
API_DOCS_USE_ACTUAL_DATA=true

Publishing Views (Optional)

Customize the HTML documentation:

php artisan vendor:publish --tag=api-docs-views

Views will be published to resources/views/vendor/api-docs/.

📚 How It Works

1. Route Detection

The package automatically scans all registered routes:

// Your routes/api.php
Route::get('/api/products', [ProductController::class, 'index']);
Route::post('/api/products', [ProductController::class, 'store']);
Route::get('/api/products/{id}', [ProductController::class, 'show']);

Automatically detected:

  • HTTP methods (GET, POST, PUT, PATCH, DELETE)
  • Route parameters ({id}, {slug}, etc.)
  • Middleware applied to routes
  • PHPDoc comments from controller methods

2. Parameter Detection

From FormRequests:

class StoreProductRequest extends FormRequest
{
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'price' => 'required|numeric|min:0',
            'status' => 'required|in:active,inactive',
            'category_id' => 'required|exists:categories,id',
        ];
    }
}

From Method Signatures:

public function show(Request $request, int $id)
{
    // $id automatically detected as path parameter
}

From Controller Method Body:

public function index(Request $request)
{
    $query = Product::query();

    if ($request->has('search') && $request->search) {
        $query->where('name', 'like', "%{$request->search}%");
    }

    if ($request->input('category_id')) {
        $query->where('category_id', $request->category_id);
    }

    if ($request->branch_ids) {
        $query->whereIn('branch_id', $request->branch_ids);
    }

    return $query->get();
}

Automatically detects:

  • search (string) - from $request->has('search')
  • category_id (integer) - from $request->input('category_id')
  • branch_ids (array) - from $request->branch_ids (smart type detection)

Supported patterns:

  • $request->has('param')
  • $request->input('param')
  • $request->get('param')
  • $request->query('param')
  • $request->param (magic property access)

Pagination Auto-Detection:

public function index()
{
    return Product::paginate(20);
    // Automatically adds 'page' and 'per_page' parameters
}

3. Database Schema

Automatically reads table schemas:

class ProductController extends Controller
{
    public function index()
    {
        return Product::all();
        // Automatically shows 'products' table schema
    }
}

Displays:

  • Column names and types
  • Nullable fields
  • Default values
  • Maximum lengths
  • Indexes and foreign keys

4. Response Examples

Detects Collection vs Single Resource:

// Collection - returns array
public function index()
{
    return $this->sendResponse(
        RoleResource::collection($roles),
        'Roles retrieved successfully'
    );
}
// Generates: { "data": [{...}, {...}] }

// Single Resource - returns object
public function show($id)
{
    return $this->sendResponse(
        new UserResource($user),
        'User retrieved successfully'
    );
}
// Generates: { "data": {...} }

Uses Real Database Data:

class ProductResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'price' => $this->price,
            'status' => $this->status,
            'category' => new CategoryResource($this->whenLoaded('category')),
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

The package automatically:

  • Fetches the first record from the database table
  • Maps it to your Resource structure
  • Sanitizes sensitive fields (passwords, tokens, API keys)

Generated Response:

{
  "success": true,
  "status": 200,
  "message": "Success",
  "data": [
    {
      "id": 1,
      "name": "string value",
      "price": 99.99,
      "status": "active",
      "category": "string value",
      "created_at": "2025-01-15T12:00:00Z",
      "updated_at": "2025-01-15T12:00:00Z"
    }
  ],
  "meta": {
    "size": 20,
    "page": 1,
    "total_pages": 1,
    "total_items": 1
  }
}

💡 Usage Examples

Adding DocBlocks for Better Documentation

/**
 * Get all products with filtering and pagination
 *
 * Returns a paginated list of products. You can filter by category,
 * status, and search by name.
 */
public function index(ProductIndexRequest $request)
{
    return ProductResource::collection(
        Product::with('category')
            ->paginate($request->input('per_page', 20))
    );
}

Filtering Routes

Include only specific API versions:

// config/api-docs.php
'route_filters' => [
    'include_prefixes' => ['api/v1/', 'api/v2/'],
],

Exclude internal or admin routes:

'route_filters' => [
    'exclude_patterns' => [
        'api/internal/*',
        'api/admin/*',
        'telescope/*',
    ],
],

Custom Route Prefix

Change the documentation URL:

API_DOCS_ROUTE_PREFIX=documentation

Access documentation at: http://your-app.test/documentation

🎨 UI Features

Compact Table Format

Parameters are displayed in space-efficient tables instead of card grids:

Parameter Type Required Description
search string No Search by name
category_id integer No Filter by category

URL Persistence

When you select a controller, the URL updates automatically:

http://your-app.test/api-docs?controller=ProductController

Benefits:

  • Bookmark specific controllers
  • Share direct links with your team
  • Browser back/forward navigation works
  • Refresh page maintains your selection

Optimized Spacing

  • Compact typography (10px base font)
  • Reduced padding throughout
  • Smaller badges and buttons
  • More content visible on screen

Copy to Clipboard

One-click copy for:

  • cURL commands with all parameters
  • Postman collection export
  • Response examples

🔒 Security

Protect Documentation in Production

Using Middleware:

// config/api-docs.php
'middleware' => ['web', 'auth', 'admin'],

Disable in Production:

# .env.production
API_DOCS_ENABLED=false

Hide Database Schema in Production:

# .env.production
API_DOCS_SHOW_DATABASE_SCHEMA=false

This keeps the documentation accessible but hides sensitive database structure information.

Disable Real Data Examples in Production:

# .env.production
API_DOCS_USE_ACTUAL_DATA=false

This prevents exposing real database records in documentation. The package will use generated dummy data instead.

Automatic Security Sanitization:

When using real data, sensitive fields are automatically hidden:

// Original database value
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi...',
'api_key' => 'sk_live_51H7...',
'access_token' => 'eyJhbGciOiJIUzI1NiIsInR...',

// In documentation
'password' => '***HIDDEN***',
'api_key' => '***HIDDEN***',
'access_token' => '***HIDDEN***',

Protected field patterns:

  • password, secret, token
  • api_key, private_key
  • access_token, refresh_token
  • credit_card, ssn, salt

Conditional Enabling:

// config/api-docs.php
'enabled' => env('API_DOCS_ENABLED', !app()->isProduction()),

IP Whitelist Example

// config/api-docs.php
'middleware' => ['web', 'ip.whitelist'],

🔄 Integration with Swagger UI

Use the OpenAPI endpoint with Swagger UI:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" />
</head>
<body>
    <div id="swagger-ui"></div>
    <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
    <script>
        SwaggerUIBundle({
            url: '/api-docs/swagger',
            dom_id: '#swagger-ui',
        });
    </script>
</body>
</html>

🛠️ Troubleshooting

Documentation Not Appearing

  1. Clear Laravel cache:

    php artisan config:clear
    php artisan route:clear
    php artisan cache:clear
  2. Verify routes are registered:

    php artisan route:list | grep api-docs
  3. Check if package is discovered:

    php artisan package:discover

Database Schema Not Loading

PostgreSQL Configuration:

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=your_database
DB_SCHEMA=public

Update config:

// config/api-docs.php
'database' => [
    'schema' => env('DB_SCHEMA', 'public'),
],

Resources Not Detected

Ensure your Resource classes:

  1. Extend Illuminate\Http\Resources\Json\JsonResource
  2. Are in the configured namespace (default: App\Http\Resources)
  3. Follow naming convention: {Model}Resource

Example:

// app/Http/Resources/ProductResource.php
class ProductResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
        ];
    }
}

No Routes Showing

Check route filters:

// config/api-docs.php
'route_filters' => [
    'include_prefixes' => ['api/'], // Make sure your routes match
],

Verify routes exist:

php artisan route:list --path=api

🎯 Best Practices

1. Use FormRequests for Validation

class StoreProductRequest extends FormRequest
{
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'price' => 'required|numeric|min:0',
        ];
    }
}

Benefits:

  • Automatic parameter documentation
  • Type detection (string, integer, array, etc.)
  • Validation rules displayed in Request Body tab

Note: Even without FormRequests, the package detects parameters from your controller code using $request->has(), $request->input(), etc.

2. Use Laravel Resources

class ProductResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'price' => (float) $this->price,
        ];
    }
}

Benefits:

  • Accurate response examples with real database data
  • Proper data transformation
  • Consistent API responses
  • Automatic detection of array vs single object responses

Pro Tip: Use Resource::collection() for list endpoints and new Resource() for single items. The package automatically generates correct response structures.

// List endpoint - returns array
return RoleResource::collection($roles);
// Documentation shows: { "data": [{...}, {...}] }

// Single endpoint - returns object
return new RoleResource($role);
// Documentation shows: { "data": {...} }

3. Add Meaningful DocBlocks

/**
 * Update product details
 *
 * Updates an existing product with the provided data.
 * Requires authentication and product ownership.
 *
 * @param UpdateProductRequest $request
 * @param int $id Product ID
 * @return JsonResponse
 */
public function update(UpdateProductRequest $request, int $id)
{
    // ...
}

4. Use Resource Controllers

Route::apiResource('products', ProductController::class);

Benefits:

  • Standard RESTful routes
  • Consistent naming
  • Better documentation organization

📝 Changelog

Please see CHANGELOG for more information on what has changed recently.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

🔗 Links

📄 License

The MIT License (MIT). Please see License File for more information.

💖 Support

If you find this package helpful, please consider:

  • ⭐ Starring the repository on GitHub
  • 🐛 Reporting bugs and issues
  • 💡 Suggesting new features
  • 🔀 Contributing code improvements

🙏 Credits

Built with ❤️ for the Laravel community