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 (2)

Collapse
 
johanrg profile image
Johan Gustafsson

Very interesting. I have the perfect project to test this on in a couple of weeks.

Collapse
 
nameless0l profile image
Loic Aron Mbassi Ewolo

Awesome, Johan! I'd love to hear your feedback once you try it out on that project.

When you are ready to start, here is the official documentation to help you get set up quickly: doc

Also, if you use VS Code, I highly recommend grabbing the official extension link. It gives you a nice UI .

Feel free to reach out or open an issue.
Happy coding!