Version 3.0 introduces a plugin-based architecture for module auto-discovery. The monolithic ModularServiceProvider has been refactored into a collection of focused, composable Plugin classes.
This improves extensibility, testability, and separation of concerns.
- PHP 8.3+ (was 8.0+)
- Laravel 11+ (dropped Laravel 9/10 support)
| Removed | Replacement |
|---|---|
ModularEventServiceProvider |
EventsPlugin (auto-registered) |
AutoDiscoveryHelper |
FinderFactory |
ModuleRegistry::getCachePath() |
Cache::path() |
make:livewire --module |
Install internachi/modular-livewire |
| Breadcrumbs integration | Load manually in service provider |
| Before | After |
|---|---|
bootstrap/cache/modules.php |
bootstrap/cache/app-modules.php |
| Module paths only | All plugin discovery data |
PluginRegistry → Registration point for plugins
PluginHandler → Orchestrates plugin lifecycle
PluginDataRepository → Manages discovery data (cached or fresh)
Cache → File I/O for unified cache
FinderFactory → Creates FinderCollection instances
ModuleFileInfo → Decorator with module() and fullyQualifiedClassName()
abstract class Plugin
{
abstract public function discover(FinderFactory $finders): iterable;
abstract public function handle(Collection $data);
}| Attribute | Behavior |
|---|---|
#[AfterResolving(Service::class)] |
Defer until service resolved |
#[OnBoot] |
Execute during booting() hook |
| (none) | Explicit call via PluginHandler::handle() |
| Plugin | Trigger | Responsibility |
|---|---|---|
ModulesPlugin |
Eager | Discover composer.json, create ModuleConfig |
RoutesPlugin |
!routesAreCached() |
Load route files |
ViewPlugin |
AfterResolving(ViewFactory) |
Register view namespaces |
BladePlugin |
AfterResolving(BladeCompiler) |
Register Blade components |
TranslatorPlugin |
AfterResolving(Translator) |
Register translations |
EventsPlugin |
AfterResolving(Dispatcher) |
Discover event listeners |
MigratorPlugin |
AfterResolving(Migrator) |
Register migration paths |
GatePlugin |
AfterResolving(Gate) |
Register model policies |
ArtisanPlugin |
Artisan::starting() |
Register commands |
ModularServiceProvider::register()
├─ Register singletons
├─ PluginRegistry::add(built-in plugins)
└─ $app->booting(PluginHandler::boot)
└─ For each plugin:
└─ Plugin::boot(handler, app)
└─ Read attributes, schedule execution
Register custom plugins in a service provider:
public function register(): void
{
PluginRegistry::register(MyPlugin::class);
}Custom plugins:
- Must extend
InterNACHI\Modular\Plugins\Plugin - Are automatically integrated into caching
- Can use lifecycle attributes
Modular 3.0 integrates with Laravel's optimize commands via the optimizes() method:
php artisan optimize→ runsmodules:cachephp artisan optimize:clear→ runsmodules:clear
- Upgrade PHP to 8.3+ and Laravel to 11+
- Run
php artisan modules:clear - Run
composer update internachi/modular - If using Livewire:
composer require internachi/modular-livewire - Update any
AutoDiscoveryHelperreferences toFinderFactory - Remove any
ModularEventServiceProviderreferences