dcblogdev/laravel-module-generator
Generate Laravel modules in seconds with an Artisan command that scaffolds controllers, models, migrations, routes and views into a clean, self-contained module structure. Keeps large apps organised and speeds up feature development.
Install the package with Composer and publish its config:
composer require dcblogdev/laravel-module-generator
php artisan vendor:publish --tag=config # writes config/module-generator.php
The config file is the first thing to read — it controls where modules are written (path), the root namespace applied to generated classes, and the stub/asset locations the generator copies from. Change those values before generating anything; retrofitting a different path or namespace later means moving directories and fixing namespaces by hand.
Generate your first module and confirm the wiring works end to end:
php artisan module:make Blog
php artisan list module # see the full family of make:* subcommands
This scaffolds a module directory (controllers, models, views, routes, migrations, and a module service provider, depending on config/options). Then create one artifact of each kind you actually need:
php artisan module:make:controller Blog PostController
php artisan module:make:model Blog Post
php artisan module:make:migration Blog create_posts_table
Where to look next, in order:
php artisan migrate:status, this file is the cause 90% of the time.php artisan route:list --path=blog.composer.json autoload — if modules live outside app/, there must be a PSR-4 mapping for the module namespace.First realistic use case: a self-contained "Blog" module with an index route, a controller, an Eloquent model, a migration, and a Blade view — the whole vertical slice in one directory instead of scattered across app/Http, app/Models, resources/views, and routes/.
Treat it as a scaffolder, not a runtime module system. The package's job is generating boilerplate; the resulting code is ordinary Laravel code in a namespaced directory. There is no module registry, enable/disable toggle, or dependency graph. If you need those, that's a different package or your own convention.
One module per bounded context. The pattern only pays off when a module maps to a business capability (Billing, Inventory, Reporting) rather than a layer (Controllers, Models). Modules that hold one controller each just add a directory level.
CRUD slice workflow. Generate the module, then generate model + migration + controller + request + resource + factory + seeder in one pass, writing the migration and routes by hand. Keep the module's routes file thin — a resource route plus a couple of custom actions — and put authorization in policies or the generated form request rather than the controller.
Register the provider, then forget it. On Laravel 11+/12/13, add the module provider to bootstrap/providers.php; on older skeletons, config/app.php. Do this once per module and commit it. Anything the module exposes to the rest of the app (routes, views, migrations, translations, Blade components) is registered from that provider, so it's also the single place to look when something is "missing."
Cross-module communication goes through the framework, not through imports. Events/listeners, contracts bound in a service provider, or plain queued jobs. Direct use App\Modules\Billing\Models\Invoice; from inside another module is the fastest way to end up with a tangle that defeats the point of the structure.
Namespaced views. Generated views are referenced through a namespace registered by the module provider (the generated controller shows the exact syntax). Use the namespaced form consistently — mixing view('blog::posts.index') with view('modules.blog.posts.index') makes views impossible to locate later.
Testing. Feature tests work normally: RefreshDatabase, $this->get(route('blog.posts.index')). Because modules register their own migration paths, RefreshDatabase picks them up as long as the provider is registered in the test environment — verify this early, since a silently-missing migration path produces confusing "no such table" failures.
CI/deploy. Add composer dump-autoload after any module is added or renamed, and clear caches (config:clear, route:clear, view:clear) on deploy. If you generate modules in CI rather than committing them, run the generator before the autoload dump.
composer dump-autoload. If a freshly generated class gives "not found," dump autoload before debugging anything else. Modules outside app/ require an explicit PSR-4 entry in composer.json.config/module-generator.php, run php artisan config:clear. With a cached config (production default), generators keep writing to the old location.php artisan route:cache is regenerated. A module that works locally and 404s in staging is almost always this.loadMigrationsFrom() in the module provider; if you hand-write a module or copy one, that call is easy to omit and php artisan migrate will silently skip the module. Use php artisan migrate --path=... to isolate a single module's migrations while debugging. Migration ordering across modules is filename-timestamp based, so cross-module foreign keys need care.Post model is fine for PHP but painful for Eloquent relationship strings, which are resolved by FQCN. Always use the full namespace, and pass Post::class, not 'Post', to hasMany/belongsTo.Blog, OrderManagement). Lowercase names generate directories that behave differently on case-insensitive macOS filesystems versus Linux containers — a class of bug that only appears after deploy.make command against an existing module can clobber previously edited files. Commit (or stash) before regenerating, and prefer generating into a fresh module over re-running on a live one.Database\Factories guess — override newFactory() or set $factory-style resolution explicitly.php artisan list module enumerates what's actually available in your installed version (the command set has grown over releases and isn't identical across majors); php artisan route:list --path=<module> and php artisan migrate:status confirm registration. Use -v on generator commands for the paths being written.How can I help you explore Laravel packages today?