DEV Community

Cover image for Turning an existing database into a documented Laravel API
Loic Aron Mbassi Ewolo
Loic Aron Mbassi Ewolo

Posted on

Turning an existing database into a documented Laravel API

The projects I dread are the ones where the database is the only documentation. Twenty tables, foreign keys, years of production data, and either no API layer at all or a pile of copy-pasted controllers nobody wants to touch.

Writing models, controllers, validation and tests for twenty existing tables by hand takes days. This is the problem that made me add --from-database to laravel-api-generator:

composer require --dev nameless/laravel-api-generator
php artisan make:fullapi --from-database
Enter fullscreen mode Exit fullscreen mode

The generator reads your live schema and produces, for each table, the same stack it builds in normal mode: model with full PHPDoc, thin controller, service, DTO, form requests with real validation rules, resource, factory, seeder, policy, and written tests (PHPUnit, or Pest with --pest).

[GIF demo-from-database.gif (voir fichier 12) : vraie exécution en terminal, pas Claude Design]

What the introspection actually reads

I spent a lot of time making this more than a column dump.

A VARCHAR(255) NOT NULL UNIQUE column doesn't just become a string field. It becomes required|string|max:255|unique:users,email in the form request and fake()->unique()->safeEmail() in the factory.

Foreign keys turn into relations on both sides: posts.user_id gives you Post::user(): BelongsTo and User::posts(): HasMany, both typed in the PHPDoc. On Laravel 11+ the generator reads the real constraints; it also falls back to the <table>_id naming convention for older schemas without them.

Pivot tables are detected (two foreign keys and nothing else) and become belongsToMany on both models, instead of generating a useless PostTag entity. Column pairs like commentable_type + commentable_id become a proper morphTo. Enum columns become native PHP backed enums with casts and Rule::enum validation. A deleted_at column switches the whole entity to soft deletes, restore endpoint included.

You rarely want all tables

php artisan make:fullapi --from-database --tables=posts,categories,comments
Enter fullscreen mode Exit fullscreen mode

Two defaults exist to save you from yourself: migrations are not regenerated (the tables already exist; pass --with-migrations if you want them as code-of-record), and the users table is skipped so your customized User.php survives. --tables=users overrides that explicitly.

The payoff

The generated controllers are Scramble-friendly, so if you have Scramble installed, /docs/api serves browsable OpenAPI docs immediately. Add --postman and you can hand a collection to the frontend team the same morning.

If the team lives in VS Code, the extension runs the same import from a table picker, and its Open API Docs button closes the loop: it checks Scramble, starts the server if none is running, detects the port and opens the docs in the browser. It even offers to create .env from .env.example on a fresh checkout.

Legacy database at 9:00, documented and tested API at 9:15. The business logic still needs a human. The plumbing doesn't.

Notes

The package is a --dev dependency and the generated code doesn't depend on it, so you can treat it as a one-shot migration tool if that's all you need.

If you have a schema that you think would break it, I want to see it. Weird databases are how this feature got better.

Top comments (0)