Data models get designed in diagrams and implemented in code, and the two drift apart from day one. The diagram in your README says Post belongsTo Category; the code says otherwise; nobody notices until a migration fails.
The fix I landed on for laravel-api-generator: make the diagram the input. Two formats work, YAML and Mermaid.
YAML
# api-schema.yaml
options:
pest: true
postman: true
entities:
Category:
fields:
name: string unique
relations:
posts: hasMany Post
Post:
fields:
title: string
content: text
status: enum(draft,published) default=draft
published_at: datetime nullable
php artisan make:fullapi --schema=api-schema.yaml
Look at what's missing: Post never declares belongsTo Category, and there's no category_id field anywhere. The generator synthesizes the inverse relation and its foreign key column. You declare one side, like you would explain it to a colleague, and both sides exist in the code.
The enum line generates the backed enum class, the model cast, Rule::enum validation and a factory that picks random cases. I wrote about that chain in more detail in part 1.
This is the one I use most, because GitHub renders it in the PR:
Mermaid
php artisan make:fullapi --mermaid=docs/erd.mmd
Both erDiagram and classDiagram work. Cardinalities map to the right Eloquent relations, UK markers become unique fields, a deleted_at column enables soft deletes. Markdown fences and comments are stripped, so a diagram pasted straight from an AI chat works as-is. Review the diagram in the pull request, merge, generate. No drift, because there's nothing to drift from.
The VS Code extension takes the same Mermaid input without the terminal, and it draws the reverse view too: an interactive diagram of your entities (zoom, pan) inside the editor. The diagram goes in, the API comes out, and the canvas shows you what actually exists.
[VISUEL 15 (fichier 13) : vraie capture du diagramme interactif de l'extension, habillée]
[VISUEL 10 (fichier 13) : split-screen diagramme Mermaid rendu / arborescence générée]
Custom primary keys propagate
Country:
fields:
code: string primary
name: string
relations:
cities: hasMany City
This was the request that took me the longest in v3.6. City gets a country_code column typed like the key, ->references('code') in the migration, exists:countries,code in validation, and the model declares $primaryKey, $incrementing and $keyType. The generated tests use getKey() so the same suite passes with either key style. Polymorphic relations (morphTo, morphOne, morphMany) are supported in schemas too.
Day 30
Every scaffolder demos well on day 1 and gets deleted on day 30, because regenerating would wipe your manual work. So regeneration isn't the evolution path here. Patching is:
php artisan make:fullapi Post --add-fields="excerpt:text,seo_title:string"
This writes an incremental Schema::table migration with a down(), and patches $fillable, the casts, the PHPDoc, the validation rules, the factory and the resource in place. Your custom methods are not touched. Fields that already exist are skipped. The DTO and the tests are deliberately left alone and reported as manual follow-ups, because guessing there felt more dangerous than useful.
Practical notes
Dev dependency, MIT, generated code has no reference to the package. Works in CI and with AI coding agents; one YAML file describing the whole API turns out to be a much better target for an agent than "create twelve files". The extension mentioned above also adds a form builder with live preview, imports from a database or an OpenAPI spec, and one-click migrate, seed and docs.
- Docs: https://nameless0l.github.io/laravel-api-generator/
- GitHub: https://github.com/Nameless0l/laravel-api-generator
- Part 1 (architecture): link · Part 2 (
--from-database): link
If you have opinions about what a schema format should support, the issues are open. Mine changed three times while building this.

Top comments (0)