This guide will help you quickly integrate custom modules into your Laravel application.
php artisan module create MyModuleThis creates a complete module structure at app/Modules/MyModule/.
Edit app/Modules/MyModule/module.json:
{
"name": "MyModule",
"version": "1.0.0",
"description": "My custom module for specific functionality",
"dependencies": [],
"config": {
"enabled": false
}
}Edit app/Modules/MyModule/MyModuleModule.php:
<?php
namespace App\Modules\MyModule;
use App\Modules\BaseModule;
class MyModuleModule extends BaseModule
{
protected function onEnable(): void
{
// Initialize your module
\Log::info('MyModule enabled');
}
protected function onInstall(): void
{
// Run installation tasks
\Log::info('MyModule installed');
}
}# Install the module (runs migrations, publishes assets)
php artisan module install MyModule
# Or just enable it (if already installed)
php artisan module enable MyModulephp artisan module list
php artisan module info MyModuleEdit routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use App\Modules\MyModule\Http\Controllers\MyController;
Route::middleware(['web'])->prefix('mymodule')->group(function () {
Route::get('/', [MyController::class, 'index'])->name('mymodule.index');
Route::get('/dashboard', [MyController::class, 'dashboard'])->name('mymodule.dashboard');
});Create controller at Http/Controllers/MyController.php:
<?php
namespace App\Modules\MyModule\Http\Controllers;
use App\Http\Controllers\Controller;
class MyController extends Controller
{
public function index()
{
return view('mymodule::index');
}
public function dashboard()
{
return view('mymodule::dashboard');
}
}Create migration in database/migrations/2024_01_01_000000_create_mymodule_table.php:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('mymodule_items', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description')->nullable();
$table->boolean('active')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('mymodule_items');
}
};The migration runs automatically when you install the module.
Create resources/views/index.blade.php:
@extends('layouts.app')
@section('content')
<div class="container">
<h1>My Module</h1>
<p>Welcome to my custom module!</p>
</div>
@endsectionAccess it via: return view('mymodule::index');
Create Services/MyService.php:
<?php
namespace App\Modules\MyModule\Services;
class MyService
{
public function processData($data)
{
// Your business logic
return $data;
}
}Register in Providers/MyModuleServiceProvider.php:
<?php
namespace App\Modules\MyModule\Providers;
use Illuminate\Support\ServiceProvider;
use App\Modules\MyModule\Services\MyService;
class MyModuleServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(MyService::class);
}
public function boot(): void
{
// Boot services
}
}Use in controllers:
public function __construct(protected MyService $myService)
{
}
public function process()
{
$result = $this->myService->processData($data);
}Add hooks to extend functionality:
class MyModuleModule extends BaseModule
{
protected function onEnable(): void
{
// Register custom hooks
$this->registerHook('after_data_save', function($data) {
\Log::info('Data saved', ['data' => $data]);
});
// Register multiple hooks
$this->registerHook('before_delete', function($item) {
// Cleanup before deletion
}, priority: 5);
}
public function saveData($data)
{
// Save logic here
// Execute hook
$this->executeHook('after_data_save', $data);
}
}Create config/mymodule.php:
<?php
return [
'items_per_page' => 20,
'cache_enabled' => true,
'cache_ttl' => 3600,
'features' => [
'notifications' => true,
'export' => true,
],
];Use in your module:
// Get config value
$perPage = $this->config('items_per_page', 10);
// Set runtime config
$this->setConfig('cache_enabled', false);
// Get all config
$allConfig = $this->getAllConfig();If your module depends on other modules, declare them in module.json:
{
"name": "AdvancedModule",
"dependencies": ["CoreModule", "AuthModule"]
}The system will automatically ensure dependencies are enabled before allowing this module to be enabled.
Create tests/MyModuleTest.php:
<?php
namespace Tests\Modules\MyModule;
use Tests\TestCase;
use App\Modules\MyModule\MyModuleModule;
use App\Modules\MyModule\Services\MyService;
class MyModuleTest extends TestCase
{
public function test_module_can_be_created()
{
$module = new MyModuleModule();
$this->assertInstanceOf(MyModuleModule::class, $module);
}
public function test_service_processes_data()
{
$service = app(MyService::class);
$result = $service->processData(['test' => 'data']);
$this->assertNotNull($result);
}
}Run tests:
php artisan test --filter MyModule# List all modules
php artisan module list
# Create new module
php artisan module create ModuleName
# Install module (migrations + enable)
php artisan module install ModuleName
# Enable module
php artisan module enable ModuleName
# Disable module
php artisan module disable ModuleName
# Uninstall module (requires confirmation)
php artisan module uninstall ModuleName
# Show module information
php artisan module info ModuleNameIf your module has CSS/JS/images in resources/assets/:
resources/assets/
├── css/
│ └── style.css
├── js/
│ └── script.js
└── images/
└── logo.png
They will be published to public/modules/MyModule/ during installation.
Use in Blade templates:
<link href="{{ asset('modules/MyModule/css/style.css') }}" rel="stylesheet">
<script src="{{ asset('modules/MyModule/js/script.js') }}"></script>
<img src="{{ asset('modules/MyModule/images/logo.png') }}" alt="Logo">- Keep it simple - Start with minimal functionality and expand
- Test early - Write tests as you develop
- Document - Add clear comments and update module.json
- Use hooks - Leverage the hook system for extensibility
- Handle errors - Always wrap risky operations in try-catch
- Follow conventions - Use Laravel's naming and structure conventions
- Version properly - Use semantic versioning
- Check dependencies - Always declare module dependencies
Here's a complete example of a simple product catalog module:
// ProductCatalogModule.php
<?php
namespace App\Modules\ProductCatalog;
use App\Modules\BaseModule;
class ProductCatalogModule extends BaseModule
{
protected function onEnable(): void
{
$this->registerHook('product_created', function($product) {
\Log::info("Product created: {$product->name}");
});
}
protected function onInstall(): void
{
// Seed default categories
\DB::table('product_categories')->insert([
['name' => 'Electronics', 'slug' => 'electronics'],
['name' => 'Clothing', 'slug' => 'clothing'],
]);
}
}// Http/Controllers/ProductController.php
<?php
namespace App\Modules\ProductCatalog\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Modules\ProductCatalog\Models\Product;
class ProductController extends Controller
{
public function index()
{
$products = Product::paginate(20);
return view('productcatalog::products.index', compact('products'));
}
public function show($id)
{
$product = Product::findOrFail($id);
return view('productcatalog::products.show', compact('product'));
}
}The application includes a web-based installer that can manage modules through a graphical interface.
- Set
INSTALLER_ENABLED=truein your.envfile - Optionally set
INSTALLER_KEY=your-secret-keyfor authentication - Access the installer at
http://your-domain/installer.php
The installer provides a "Modules" section where you can:
-
List All Modules
- Click "List Modules" to see all available modules
- View module status (Enabled/Disabled), version, and description
-
Enable a Module
- Find the module in the list
- Click "Enable" to activate it without running migrations
- Useful for modules already installed
-
Install a Module
- Find the module in the list
- Click "Install" to:
- Run module migrations
- Publish module assets
- Execute installation hooks
- Enable the module
- The installer requires
vendor/autoload.phpto exist (run Composer install first) - All module operations are logged to
storage/logs/laravel.log - After enabling/installing modules, clear cache:
php artisan config:clear php artisan route:clear
- Security: Disable the installer after setup by setting
INSTALLER_ENABLED=false
- Read the full Module Development Guide
- Study the example
BlogModuleinapp/Modules/BlogModule/ - Explore the source code in
app/Modules/ - Join our community for support and examples
- Check the Module Development Guide for detailed documentation
- Review example modules in
app/Modules/ - Check logs in
storage/logs/for debugging - Open an issue on GitHub for bugs or feature requests
Happy module development! 🚀