nwidart/laravel-modules
Laravel package for structuring large apps into self-contained modules (like mini packages) with their own controllers, models, views, routes, and config. Includes Artisan generators, module discovery, and configuration for organizing and scaling projects.
Installation:
composer require nwidart/laravel-modules
The package auto-registers its service provider and aliases.
Publish Configuration (Optional but recommended):
php artisan vendor:publish --provider="Nwidart\Modules\LaravelModulesServiceProvider"
Enable Autoloading:
Add to composer.json:
"extra": {
"merge-plugin": {
"include": ["Modules/*/composer.json"]
}
}
Run:
composer dump-autoload
Create Your First Module:
php artisan module:make Blog
This generates a module skeleton in Modules/Blog/ with:
ModuleServiceProviderroutes/web.php/routes/api.phpHttp/Controllers/ (empty by default)Database/Migrations/Resources/views/Enable the Module:
php artisan module:enable Blog
Verify:
Check php artisan module:list to confirm the module is enabled.
Generate a Model:
php artisan module:make-model Blog/Post -m
This creates:
Database/Models/Post.phpDatabase/Migrations/[timestamp]_create_posts_table.phpRun Migrations:
php artisan migrate
Define Routes (in Modules/Blog/routes/web.php):
Route::resource('posts', 'PostsController');
Generate a Controller (if not auto-generated):
php artisan module:make-controller Blog/PostsController --resource
php artisan and filter by module: prefix.Modules/[ModuleName]/ follows Laravel conventions but is isolated.config/modules.php (customize paths, namespaces, etc.).Create a Module:
php artisan module:make [name] [--namespace="Module\\Namespace"]
Example: php artisan module:make Admin --namespace="App\\Modules\\Admin"
Generate Assets: Use Laravel’s generators with module-specific flags:
php artisan module:make-model Admin/User -m
php artisan module:make-controller Admin/UsersController --resource --api
php artisan module:make-migration create_users_table --module=Admin
Seed Data:
php artisan module:seed Admin --class=AdminDatabaseSeeder
Compile Assets:
Modules support Laravel Mix/Vite. Add a vite.config.js or webpack.mix.js to the module root and use:
php artisan module:build Admin
RouteServiceProvider (auto-generated at Modules/[Module]/RouteServiceProvider.php).Modules/[Module]/routes/web.php or routes/api.php.ModuleServiceProvider (e.g., Modules/Blog/ModuleServiceProvider.php).boot() method:
public function boot()
{
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->registerRoutes();
$this->registerPolicies();
}
Modules/[Module]/Resources/views/.vite.config.js (module root):
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
php artisan module:build [module].Modules/[Module]/Database/Migrations/.Modules/[Module]/Database/Seeders/.php artisan migrate --module=Blog
php artisan db:seed --class=BlogDatabaseSeeder
--module flag in phpunit.xml:
<env name="MODULES" value="Blog,Admin"/>
module() helper to load a module in tests:
use Nwidart\Modules\Facades\Module;
Module::load('Blog');
Modules/[Module]/module.json:
{
"require": ["Auth", "Database"]
}
php artisan module:enable [module] to load dependencies.config/modules.php:
'paths' => [
'modules' => base_path('Modules'),
],
'namespace' => 'Modules',
config_path('modules.php') to customize paths/namespaces.ModuleServiceProvider:
public function boot()
{
$this->app['router']->middleware('web', \App\Http\Middleware\CheckBlogAuth::class);
}
app/Http/Kernel.php under $moduleMiddleware.php artisan module:make-event Blog/PostCreated
php artisan module:make-listener Blog/HandlePostCreated --event=Blog/PostCreated
ModuleServiceProvider:
public function boot()
{
$this->app->make('Blog\Events\PostCreated')->listen(function ($event) {
// Handle event
});
}
php artisan module:make-resource Blog/PostResource
return new PostResource(Post::all());
php artisan module:make-command Blog/GenerateSitemap
ModuleServiceProvider:
protected $commands = [
\Modules\Blog\Commands\GenerateSitemap::class,
];
php artisan module:v6:migrate
\Nwidart\Modules\Activators\DatabaseActivator:
use Nwidart\Modules\Activators\DatabaseActivator;
class CustomActivator extends DatabaseActivator
{
protected $table = 'module_statuses';
}
config/modules.php:
'activator' => \App\Activators\CustomActivator::class,
Class not found errors for module classes.composer dump-autoload or incorrect merge-plugin config.composer.json has:
"extra": {
"merge-plugin": {
"include": ["Modules/*/composer.json"]
}
}
composer dump-autoload./posts in both Blog and Admin).Route::prefix('blog')->group(function () {
Route::resource('posts', 'PostsController');
});
--api/--web flags to segregate routes.Table already exists.php artisan migrate withoutHow can I help you explore Laravel packages today?