Zero-config Composer plugin for local module autoloading in Momo Framework.
🇬🇧 English · 🇷🇺 Русская версия
momo-framework/discovery is a Composer plugin (composer-plugin type) that automatically registers local module namespaces after every composer dump-autoload. Drop a module into modules/ and its PSR-4 namespaces are available immediately without any edits to the root composer.json.
MomoPlugin subscribes to POST_AUTOLOAD_DUMP. On every trigger it instantiates ModuleScanner, which walks modules/*/composer.json files and collects PSR-4 declarations. ModuleAutoloadWriter then writes the result to bootstrap/cache/modules-autoload.php — a small PHP file that calls $loader->addPsr4() for each discovered namespace. The kernel's LoadModuleAutoload bootstrapper requires this file at application start.
composer dump-autoload
│
▼
POST_AUTOLOAD_DUMP (MomoPlugin)
│
├─ ModuleScanner::scan()
│ reads modules/*/composer.json
│ collects autoload.psr-4 entries
│ resolves paths relative to each module root
│
└─ ModuleAutoloadWriter::write()
writes bootstrap/cache/modules-autoload.php
- PHP >= 8.5
- Composer 2
composer require momo-framework/discoveryBecause the package declares "type": "composer-plugin", Composer activates it automatically after installation. No further configuration is needed.
MomoPlugin implements Composer's PluginInterface and EventSubscriberInterface. It subscribes to ScriptEvents::POST_AUTOLOAD_DUMP and delegates to ModuleScanner and ModuleAutoloadWriter.
If no modules are found, the existing cache file is deleted and the plugin reports no local modules found. If modules are found, the cache is (re)written and the plugin reports the count and namespaces injected.
ModuleScanner::scan() iterates every subdirectory of modules/, reads its composer.json, and extracts all autoload.psr-4 entries. Relative paths in composer.json are resolved to absolute paths anchored to the module root.
// Returns: ['Momo\\Module\\Shop\\' => ['/path/to/modules/Shop/src']]
$additions = (new ModuleScanner($rootDir))->scan();ModuleAutoloadWriter::write() converts the namespace map into a PHP file that the kernel requires during boot. Paths inside the project root are expressed as __DIR__ . '/../../...' expressions to keep the cache portable.
Generated file example:
<?php
// modules-autoload.php @generated by momo-framework/discovery
// Do not edit — regenerated on every composer dump-autoload
/** @var \Composer\Autoload\ClassLoader $loader */
$loader->addPsr4('Momo\\Module\\Shop\\', [__DIR__ . '/../../modules/Shop/src']);
$loader->addPsr4('Momo\\Module\\Billing\\', [__DIR__ . '/../../modules/Billing/src']);Each module in modules/ needs a composer.json with at minimum a name and autoload.psr-4 section. There is no require block — all modules share the root vendor/ directory.
{
"name": "momo-module/shop",
"type": "momo-module",
"autoload": {
"psr-4": {
"Momo\\Module\\Shop\\": "src/",
"Momo\\Module\\Shop\\Database\\Migrations\\": "database/migrations/"
}
},
"extra": {
"momo": {
"providers": ["Momo\\Module\\Shop\\Providers\\ShopServiceProvider"]
}
}
}composer dump-autoload
# momo-discovery: injected 2 local module namespace(s): Momo\Module\Shop\, Momo\Module\Billing\The make:module command (from momo-framework/modules) also rebuilds the cache immediately after scaffolding, so a dump-autoload is not required after creating a new module via the CLI.
| Local module | Vendor module | |
|---|---|---|
| Location | modules/ |
vendor/ |
| Autoload | Injected by this plugin | Standard Composer |
| Dependencies | Shared via root composer.json |
Own composer.json |
| Editable | Yes — generators work directly | No — module:publish first |
composer lint
composer stan
composer rector:check
composer test
composer ci