| Install | |
|---|---|
composer require phpsamurai/laravel-module-maker |
|
| Latest Version: | 1.0.2 |
| PHP: | ^8.2 |
Build scalable, maintainable Laravel applications with self-contained HMVC modules.
One command. Complete module. Zero configuration.
Quick Start β’ Features β’ Commands β’ Examples β’ Support
Laravel Module Maker is a powerful package that generates complete, production-ready modules for your Laravel applications using the HMVC (Hierarchical Model-View-Controller) pattern.
Traditional Laravel App Your App After Module Maker
βββββββββββββββββββββ ββββββββββββββββββββββββββββββ
app/ modules/
βββ Controllers/ βββ Product/
β βββ UserController βββ Controllers/
β βββ ProductController βββ Models/
β βββ OrderController βββ Views/
β βββ ... (100+ files) βββ Routes/
βββ Models/ βββ Tests/
β βββ ... (50+ files) βββ ... (self-contained)
βββ ... (messy!) βββ Order/
β βββ ... (self-contained)
β Hard to maintain βββ User/
β Tight coupling βββ ... (self-contained)
β Difficult to scale
β
Easy to maintain
β
Loose coupling
β
Scales effortlessly
php artisan make:module Product --type=full
You get: A complete, self-contained module with API, UI, database, tests, and more. In 2 seconds.
| π Module Types | π§ Automation | π¦ Management | π¨ UI/UX |
|---|---|---|---|
| Full-Stack | Auto-register providers | List modules | Tailwind CSS |
| API-only | Auto-update composer | Delete safely | Alpine.js |
| Livewire-only | Auto-add navigation | Health checks | Responsive |
| With relationships | Auto-register routes | Dashboard | Real-time validation |
PHP >= 8.2
Laravel >= 12.0
Composer >= 2.0
Livewire >= 3.0 (optional, for Livewire modules)
composer require phpsamurai/laravel-module-maker
Optional: For Livewire modules:
composer require livewire/livewire
That's it! Ready to use. No configuration needed.
php artisan make:module Blog --type=full
php artisan migrate
http://your-app.test/blogshttp://your-app.test/api/blogsphp artisan module:dashboard
Done! Your module is ready with UI, API, database, tests, and navigation. π
| Type | Command | What You Get | Use Case |
|---|---|---|---|
|
π Full-Stack Recommended |
|
β’ API Controller |
Complete features needing both UI and API |
| π API |
|
β’ API Controller |
Backend services, REST APIs, microservices |
| β‘ Livewire |
|
β’ Livewire Components |
UI for existing APIs, frontend features |
# Interactive mode (prompts for type)
php artisan make:module Product
# Full-Stack module (API + Livewire)
php artisan make:module Product --type=full
# API module (backend only)
php artisan make:module Product --type=api
# Livewire module (UI only)
php artisan make:module Product --type=livewire
# With relationships
php artisan make:module-with-relations OrderItem \
--type=full \
--belongs-to=Order \
--belongs-to=Product \
--has-many=Review
# With options
php artisan make:module Product --force --no-tests --no-seeders
# Interactive dashboard
php artisan module:dashboard
# List all modules
php artisan list:modules
# Check module health
php artisan module:health Product
# Check all modules health
php artisan module:health
# Delete module (with confirmation)
php artisan delete:module Product
# Force delete (no confirmation)
php artisan delete:module Product --force
# Publish configuration
php artisan vendor:publish --tag=module-maker-config
# Publish stub templates
php artisan vendor:publish --tag=module-maker-stubs
modules/Product/
β
βββ π Controllers/
β βββ ProductApiController.php # RESTful API with search, filter, pagination
β
βββ π Livewire/
β βββ Index.php # List with real-time search & delete
β βββ Create.php # Create form with validation
β βββ Edit.php # Edit form with validation
β
βββ π Models/
β βββ Product.php # Eloquent model with scopes
β
βββ π Views/
β βββ livewire/
β βββ index.blade.php # Tailwind styled list view
β βββ create.blade.php # Tailwind styled form
β βββ edit.blade.php # Tailwind styled form
β
βββ π Routes/
β βββ web.php # Livewire routes (/products)
β βββ api.php # API routes (/api/products)
β
βββ π Http/
β βββ Resources/
β β βββ ProductResource.php # JSON resource transformer
β β βββ ProductCollection.php # JSON collection wrapper
β βββ Middleware/ # Ready for custom middleware
β βββ Requests/ # Ready for form requests
β
βββ π Database/
β βββ Migrations/
β β βββ 2025_xx_xx_create_product_table.php
β βββ Seeders/
β β βββ ProductSeeder.php # Sample data seeder
β βββ Factories/
β βββ ProductFactory.php # Factory for testing
β
βββ π Tests/
β βββ Feature/
β β βββ ProductTest.php # HTTP endpoint tests
β βββ Unit/
β βββ ProductTest.php # Model unit tests
β
βββ π Providers/
β βββ ProductServiceProvider.php # Auto-registered provider
β
βββ π Config/ # Module-specific config
Total: 18 files, ~35 KB, Production-ready
When you run php artisan make:module Product --type=full:
|
β File Generation
β Registration
|
β Configuration
β UI Enhancement
|
php artisan migrate
That's it! Everything else is automatic. π
namespace Modules\Product\Controllers;
class ProductApiController
{
public function index(Request $request): JsonResponse
{
$query = Product::query();
// π Built-in search
if ($request->has('search')) {
$query->where('name', 'like', "%{$request->search}%");
}
// π― Built-in filtering
if ($request->has('is_active')) {
$query->where('is_active', $request->is_active);
}
// π Built-in pagination
$products = $query->paginate(15);
return response()->json(new ProductCollection($products));
}
// β
store(), show(), update(), destroy() included
}
namespace Modules\Product\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
class Index extends Component
{
use WithPagination;
public $search = '';
public $confirmingDeletion = false;
// π Real-time search
protected $queryString = ['search'];
// ποΈ Delete with confirmation
public function delete($id)
{
$this->confirmingDeletion = true;
$this->deletingId = $id;
}
public function render()
{
$products = Product::query()
->when($this->search, fn($q) =>
$q->where('name', 'like', "%{$this->search}%")
)
->latest()
->paginate(15);
return view('products::livewire.index', [
'products' => $products
]);
}
}
// Web Routes (Livewire UI)
Route::get('/products', Index::class)->name('products.index');
Route::get('/products/create', Create::class)->name('products.create');
Route::get('/products/{product}/edit', Edit::class)->name('products.edit');
// API Routes (JSON)
Route::prefix('products')->group(function () {
Route::get('/', [ProductApiController::class, 'index']);
Route::post('/', [ProductApiController::class, 'store']);
Route::get('/{product}', [ProductApiController::class, 'show']);
Route::put('/{product}', [ProductApiController::class, 'update']);
Route::delete('/{product}', [ProductApiController::class, 'destroy']);
});
Navigation links are added automatically!
php artisan make:module Product --type=full
Before:
<nav>
<a href="/">Home</a>
<a href="/orders">Orders</a>
</nav>
After:
<nav>
<a href="/">Home</a>
<a href="/orders">Orders</a>
<a href="/products">Products</a> β Added automatically!
</nav>
Features:
See everything at a glance!
php artisan module:dashboard
Output:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ποΈ LARAVEL MODULE MAKER DASHBOARD ποΈ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π MODULE STATISTICS
Total Modules: 5
Full-Stack Modules: 3
API Modules: 2
Livewire Modules: 0
Total Routes: 45
Total Files: 85
Total Size: 250.5 KB
π¦ YOUR MODULES
ββββββββββββ¬βββββββββββββ¬βββββββββ¬ββββββββββ
β Module β Type β Routes β Health β
ββββββββββββΌβββββββββββββΌβββββββββΌββββββββββ€
β Category β Full-Stack β 9 β β
100% β
β Order β Full-Stack β 9 β β
100% β
β Product β Full-Stack β 9 β β
100% β
β Tag β API β5 β β
100% β
β UserUI β Livewire β 3 β β
100% β
ββββββββββββ΄βββββββββββββ΄βββββββββ΄ββββββββββ
β‘ QUICK ACTIONS
β’ Create: php artisan make:module {name} --type=full
β’ Health: php artisan module:health {name}
β’ Delete: php artisan delete:module {name}
Monitor your modules' health!
# Check single module
php artisan module:health Product
# Check all modules
php artisan module:health
10-Point Health Check:
Health Scores:
Generate modules with relationships built-in!
php artisan make:module-with-relations OrderItem \
--type=full \
--belongs-to=Order \
--belongs-to=Product \
--has-many=Review
Automatically generates:
In Model:
public function order()
{
return $this->belongsTo(\Modules\Order\Models\Order::class);
}
public function product()
{
return $this->belongsTo(\Modules\Product\Models\Product::class);
}
public function reviews()
{
return $this->hasMany(\Modules\Review\Models\Review::class);
}
In Migration:
$table->foreignId('order_id')->constrained()->onDelete('cascade');
$table->foreignId('product_id')->constrained()->onDelete('cascade');
# Step 1: Create product catalog
php artisan make:module Product --type=full
php artisan migrate
# Step 2: Create orders with relationships
php artisan make:module-with-relations Order \
--type=full \
--has-many=OrderItem
# Step 3: Create order items with relationships
php artisan make:module-with-relations OrderItem \
--type=full \
--belongs-to=Order \
--belongs-to=Product
# Step 4: View dashboard
php artisan module:dashboard
# Done! You have:
# β
Product catalog with UI and API
# β
Order management with relationships
# β
Order items linked to orders and products
# β
All navigation links added automatically
# Backend API
php artisan make:module Post --type=api
php artisan make:module Comment --type=api
# Frontend UIs
php artisan make:module BlogPublic --type=livewire
php artisan make:module BlogAdmin --type=livewire
# Result: Separate backend and multiple frontends!
# Core modules
php artisan make:module User --type=full
php artisan make:module Subscription --type=full
php artisan make:module Payment --type=full
# Feature modules
php artisan make:module Analytics --type=api
php artisan make:module Reporting --type=api
# UI modules
php artisan make:module Dashboard --type=livewire
php artisan make:module Settings --type=livewire
# Check everything
php artisan module:dashboard
| Method | Endpoint | Features |
|---|---|---|
GET |
/api/products |
List, search, filter, paginate, sort |
POST |
/api/products |
Create with validation |
GET |
/api/products/{id} |
Show single resource |
PUT |
/api/products/{id} |
Update with validation |
DELETE |
/api/products/{id} |
Delete resource |
# List products
curl http://your-app.test/api/products
# Search
curl "http://your-app.test/api/products?search=laptop"
# Filter
curl "http://your-app.test/api/products?is_active=1"
# Paginate
curl "http://your-app.test/api/products?page=2"
# Create
curl -X POST http://your-app.test/api/products \
-H "Content-Type: application/json" \
-d '{"name":"Laptop","description":"Gaming laptop"}'
# Update
curl -X PUT http://your-app.test/api/products/1 \
-H "Content-Type: application/json" \
-d '{"name":"Updated Laptop"}'
# Delete
curl -X DELETE http://your-app.test/api/products/1
Response Format:
{
"data": [
{
"id": 1,
"name": "Product Name",
"description": "Description",
"is_active": true,
"created_at": "2025-10-09T12:00:00.000000Z"
}
],
"meta": {
"total": 100,
"per_page": 15,
"current_page": 1
}
}
Index Component:
Create Component:
Edit Component:
<div class="max-w-7xl mx-auto px-4">
<!-- Search -->
<input wire:model.live="search"
placeholder="Search products..."
class="w-full px-4 py-2 border rounded-lg">
<!-- Results -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4">
@foreach($products as $product)
<div class="bg-white p-6 rounded-lg shadow">
<h3>{{ $product->name }}</h3>
<p>{{ $product->description }}</p>
<button wire:click="delete({{ $product->id }})"
class="text-red-600 hover:text-red-800">
Delete
</button>
</div>
@endforeach
</div>
<!-- Pagination -->
{{ $products->links() }}
</div>
Feature Test:
public function test_product_can_be_created(): void
{
$response = $this->post(route('api.products.store'), [
'name' => 'Test Product',
'description' => 'Test description',
]);
$response->assertStatus(201);
$this->assertDatabaseHas('products', [
'name' => 'Test Product'
]);
}
Unit Test:
public function test_product_active_scope(): void
{
Product::factory()->create(['is_active' => true]);
Product::factory()->create(['is_active' => false]);
$this->assertCount(1, Product::active()->get());
}
Livewire Test:
public function test_can_create_product_via_livewire(): void
{
Livewire::test(Create::class)
->set('name', 'New Product')
->call('save')
->assertRedirect(route('products.index'));
}
# All tests
php artisan test
# Specific module
php artisan test modules/Product/Tests/
# With coverage
php artisan test --coverage
php artisan vendor:publish --tag=module-maker-config
return [
// Module directory
'path' => 'modules',
// Namespace prefix
'namespace' => 'Modules',
// Default module type
'default_type' => 'api',
// Auto-register routes
'auto_register_routes' => true,
// Route types to register
'route_registration' => 'both', // 'web', 'api', or 'both'
// Generation options
'generate_tests' => true,
'generate_seeders' => true,
'generate_factories' => true,
];
php artisan vendor:publish --tag=module-maker-stubs
Stubs copied to resources/stubs/module-maker/
Available variables:
| Variable | Output | Use |
|---|---|---|
{{module}} |
Product |
Class names |
{{moduleLower}} |
product |
Variables |
{{moduleSnake}} |
product |
Tables |
{{modulePlural}} |
Products |
Labels |
{{namespace}} |
Modules |
Namespaces |
{{moduleNamespace}} |
Modules\Product |
Full namespace |
composer dump-autoload
php artisan optimize:clear
Verify bootstrap/providers.php contains your service provider.
php artisan route:clear
php artisan route:list --name=products
Check service provider is registered.
composer require livewire/livewire
php artisan optimize:clear
Ensure @livewireStyles and @livewireScripts in layout.
php artisan view:clear
Use namespace notation: products::livewire.index
Check resources/views/components/layouts/app.blade.php exists.
The package creates it automatically for first Livewire module.
ProductCatalog, UserManagement
π’ Enterprise
|
π E-commerce
|
π± SaaS
|
π CMS
|
π Education
|
π₯ Healthcare
|
# Cache everything
php artisan route:cache
php artisan config:cache
php artisan view:cache
# Optimize autoloader
composer install --optimize-autoloader --no-dev
| Command | Description | Example |
|---|---|---|
make:module |
Create module | php artisan make:module Product --type=full |
make:module-with-relations |
Create with relationships | php artisan make:module-with-relations OrderItem --belongs-to=Order |
list:modules |
List all modules | php artisan list:modules |
module:dashboard |
Show dashboard | php artisan module:dashboard |
module:health |
Check health | php artisan module:health Product |
delete:module |
Delete module | php artisan delete:module Product |
| Option | Available On | Description |
|---|---|---|
--type={full|api|livewire} |
make:module | Module type |
--belongs-to={Model} |
make:module-with-relations | BelongsTo relationship |
--has-many={Model} |
make:module-with-relations | HasMany relationship |
--force |
make:module, delete:module | Skip confirmations |
--no-tests |
make:module | Skip test generation |
--no-seeders |
make:module | Skip seeder generation |
--no-factories |
make:module | Skip factory generation |
php artisan make:module Blog --type=fullphp artisan migrate/blogsmake:module-with-relationsWe welcome contributions!
git checkout -b feature/amazinggit commit -m 'Add amazing feature'git push origin feature/amazinggit clone https://github.com/phpsamurai/laravel-module-maker.git
cd laravel-module-maker
composer install
MIT License - see LICENSE file for details.
Need Help?
π§ Email β’ π Issues β’ π Wiki
π Initial Release
Core Features:
Automation:
Module Management:
Advanced Features:
Developer Experience:
If this package helps you build better Laravel applications:
β Star on GitHub π¬ Leave Feedback
Laravel Module Maker - Your magic wand for building modular Laravel applications.
Transform monolithic apps into modular masterpieces with a single command.