Modular Architecture & Discovery
Jengo provides an integrated modular architecture that discovers domain modules placed inside the modules/ root directory.
Each module acts as an autonomous subsystem with its own Controllers, Models, Views, Config, and Routes:
modules/
└── Blog/
├── Config/
│ └── Routes.php
└── Controllers/
└── Blog.phpCodeIgniter 4 Autoloader Limitation & Workaround
In vanilla CodeIgniter 4, the framework autoloader is initialized before third-party packages or events can register dynamic namespaces. Specifically:
Config\AutoloadConfigdoes not inherit fromCodeIgniter\Config\BaseConfig, preventing package Registrars (Config\Registrar::Autoload) from declaring dynamic namespaces or helpers.- In CLI execution (
spark),Console::run()loads routes before firing thepre_commandlifecycle event.
We submitted an upstream PR to CodeIgniter 4 (CodeIgniter4#10590) introducing an autoloader_initialized event hook.
Impact When Patch Is Not Applied
While standard HTTP requests may appear to work normally due to Jengo running ModuleDiscovery::discoverAndRegister() during the pre_system event, failing to apply this patch introduces critical subtle issues across the application:
- Testing Environment Failures:
- In PHPUnit/Pest test environments,
pre_systemandpre_commandevents do not execute the same web lifecycle. - Without the patch, module namespaces (
Modules\*) are not registered into CodeIgniter's autoloader at test boot time, resulting inClass Not Foundexceptions when testing module models, controllers, or services.
- In PHPUnit/Pest test environments,
- CLI Spark Commands & Route Listing:
- Commands such as
php spark routeswill not display routes defined inside your modules (modules/*/Config/Routes.php), even though navigating to those endpoints in the browser works. - Other CLI commands that rely on early
FileLocatorscanning will miss files contained inside module directories.
- Commands such as
- Unexpected Framework Desynchronization:
- Because
RouteCollection::loadRoutes()runs inConsole::run()before commands execute and locks$didDiscover = true, module discovery that occurs later is permanently hidden from CLI tools.
- Because
Applying the patch ensures that all module namespaces, helpers, and routes are registered uniformly across web requests, spark commands, and automated test runners.
Mitigating with the Jengo CLI Patch Command
Until the PR is merged and tagged upstream in CodeIgniter 4, Jengo provides a CLI mitigation command to patch your local development environment:
php spark jengo:modules patchThis command automatically:
- Triggers the
autoloader_initializedevent insideSYSTEMPATH . 'Boot.php'inBoot::loadAutoloader()right after autoloader initialization completes. - Appends the
autoloader_initializedlistener inapp/Config/Events.phpto runModuleDiscovery::discoverAndRegister().
You can verify the status at any time with:
php spark jengo:modules patch --checkCLI Commands
Discover Modules
Scan and list all detected modules in the project:
php spark jengo:modules discoverCache Module Mapping
Compile and cache module PSR-4 mappings to .jengo/cache/modules.php for production environments:
php spark jengo:modules cacheClear Module Cache
Purge the cached module mappings:
php spark jengo:modules clear