axn/laravel-models-generator
Generate Eloquent models directly from your existing database schema. Laravel Models Generator inspects your tables and creates ready-to-use model classes with fillable fields, relationships, and more, making it easy to bootstrap new projects or reverse-engineer legacy databases.
Version 8.0.0 changes the install instructions materially. It drops everything below Laravel 12 and requires Doctrine DBAL ^4. That means the version you install is now dictated by your app, not your preference:
| Your app | Install |
|---|---|
| Laravel 12+ (and DBAL 4 resolvable) | ^8.0 |
| Laravel 11 or older | ^7.0 — no longer supported upstream |
Check for a DBAL conflict before you start: composer why doctrine/dbal. If another dependency (an older migration package, a schema-diff tool, a reporting library) pins DBAL ^3, you cannot install 8.x without resolving that first. Do not force it with --ignore-platform-reqs.
This is still a scaffolding tool, not a runtime dependency. Treat it the way you'd treat php artisan make:model — useful for the first hour of a project, irrelevant afterwards. Install it as a dev-only dependency in a throwaway branch so it never becomes load-bearing.
Minimal path:
composer require --dev axn/laravel-models-generator:^8.0
php artisan vendor:publish --tag=config # confirm tag name from the README
Then, before running anything, point the app at a database you are willing to read from and nothing more. The generator inspects the live schema, so the first thing to verify is which connection it uses — typically a config key such as models-generator.connection that should resolve to your database.connections.* entry. Never run it against production; run it against a restored snapshot or a local dump.
Where to look first, in order:
php artisan list | grep -i model) — the README is the only source of truth here, since the exact command name and options are package-specific.The canonical first use case: you inherit a legacy MySQL schema with 40 tables and no models. Rather than hand-writing 40 classes, you generate them, review the diff, and keep the 80% that is correct (table names, $fillable, $casts, belongsTo/hasMany on simple single-column foreign keys). You then hand-fix the 20% the generator got wrong — polymorphic relations, pivot tables, and anything with a composite key.
Generate into a scratch namespace, then cherry-pick. Configure the output to something like App\Models\Generated and a app/Models/Generated/ path. Run the generator, commit the result as a single "baseline" commit, and then move classes into App\Models\ one at a time as you touch them. This gives you a reviewable history and prevents a 40-file dump from landing unreviewed in a PR.
Snapshot-based regeneration. Pin the schema it sees. Keep a database/schema/snapshot.sql (or a migrate:fresh --seed-built file) and run generation against that, not against whatever your teammate happens to have locally. Otherwise two developers generate different models from different local DB states and the diffs are noise. With 8.0.0 this is doubly important: DBAL 4's schema manager is a rewrite of DBAL 3's, so a snapshot generated under 7.x/DBAL 3 and one regenerated under 8.x/DBAL 4 may differ in comments, defaults, and length/precision metadata even when the schema is identical.
Pin the toolchain as tightly as the package. Two developers on ^8.0 can still resolve different DBAL 4 minors, and introspection output is DBAL's, not the package's. Commit a lockfile, and if you keep generated models in the repo, record the exact package + DBAL version in the baseline commit message. "Regenerated models" with an unexplained diff is nearly always a DBAL patch bump, not a schema change.
Pair it with migrations, not against them. For greenfield work the generator is the wrong tool — write migrations, then use the generator once as a sanity check on what your schema implies. For brownfield work the opposite holds: dump the existing schema into migrations first (via doctrine/dbal-backed schema introspection or a mysqldump-derived baseline migration), then generate models. Doing models first leaves you with classes that describe a schema you can't reproduce. Note that DBAL 4 changes or removes several of the introspection helpers commonly used in that "dump schema to migrations" step, so verify that path on DBAL 4 separately from the generator.
Wire it into a composer script, guarded.
"scripts": {
"models:generate": [
"@php artisan models:generate --no-interaction"
]
}
Keeping it behind a named script rather than muscle memory makes it obvious in code review that a schema-derived artifact changed.
Combine with barryvdh/laravel-ide-helper. Generated models rarely include docblocks for columns. Running ide-helper:models over the freshly generated classes gives you property annotations in one pass, which is the single highest-value follow-up step. Check that your ide-helper version is happy on Laravel 12 before you rely on it in the same session.
Factories and seeders are out of scope. This package generates models; it does not generate factories. Budget time for factory:generate-style tooling or hand-written factories separately — a generated model with no factory is only half a fixture.
8.0.0 is breaking, and the break is in the hard dependency. Dropping Laravel <12 and DBAL <4 are both major-version removals, not deprecations. Practical consequences:
Type::getName() in favour of Type::lookupName(), SchemaManager::listTableDetails(), parts of the comparator/type-mapping API). Any local stub, custom template, or small vendor patch that touched DBAL 3 internals will break. Re-derive customisations from the 8.x stubs rather than copying your 7.x edits forward.Revise the "archived, therefore dead" assumption. 8.0.0 explicitly targets Laravel 12 and DBAL 4, which is the opposite signal from an abandoned package. Check the repo banner yourself before repeating the "frozen forever" line: the accurate current posture is low-activity, but publishing framework-version compatibility releases. That doesn't make it a safe long-term dependency — it still has very few dependents and a small maintainer surface — but it does mean "no fix will ever come" is no longer a safe planning assumption, and it means you should expect a 9.0.0 whenever Laravel 13 ships (and a corresponding hard cut of 8.x support).
Overwrite behaviour is the biggest footgun. Most generators of this class either (a) skip existing files silently, leaving stale models, or (b) overwrite them, destroying your hand-written scopes, accessors, and relationship methods. Find out which mode the config selects and set it explicitly. The safe default is skip-and-report: generate, list what was skipped, and diff manually. Re-verify this after upgrading — a major version bump is exactly when a "safe default" flips.
Relationship inference is shallow. Expect correct belongsTo/hasMany on plain single-column FKs and expect trouble with: polymorphic relations (*_type/*_id pairs), composite primary keys, self-referencing hierarchies, pivot tables (they'll often be generated as full models rather than belongsToMany), and schemas without real FK constraints. If your DB has no enforced foreign keys — common in older MySQL — inference will produce almost nothing useful and you're back to hand-writing relations.
Casts and enums are where generated code ages badly, and DBAL 4 moved this ground. enum columns may map to string, json columns may map to array or stay untyped, and decimal may land as float (precision loss). Review every $casts entry. Also check $timestamps and $primaryKey detection on tables with non-standard names — a table with created_at/updated_at but a string PK is a classic misdetection. Because DBAL 4 changed type mapping, a table that cast correctly under 7.x may not under 8.x (or vice versa): diff the $casts arrays explicitly across the upgrade.
Driver differences matter. Introspection through information_schema behaves differently across MySQL, MariaDB, PostgreSQL, and SQLite. Generate against the same engine you deploy on. SQLite in particular loses type and constraint fidelity, so a SQLite-generated set of models will under-report casts and relations relative to production Postgres — and Laravel 12's SQLite-first defaults make it very easy to end up generating against a dev SQLite file by accident.
Don't commit generated code you don't understand. Since this is a one-shot scaffold, the honest workflow is: generate, review, delete what you don't keep. A committed App\Models\Generated\ directory that gets re-run quarterly is a maintenance liability, not a convenience. A major-version bump on a low-dependency-count package is your reminder to test that path in a scratch app before you trust it again.
Where to extend instead of patching. If the package ships stubs or a configurable template, customise the stub rather than editing vendor/, and port those stub edits to 8.x deliberately. If it doesn't, and you find yourself fixing the same three inference bugs repeatedly — or waiting on a Laravel 13 release that may take months — that's the signal to switch to a maintained alternative (reliese/laravel is the usual benchmark) rather than to fork this one.
How can I help you explore Laravel packages today?