JiNexus Module Manager provides a simple modular approach for jinexus-mvc applications. It
keeps an ordered registry of module namespaces and resolves any of them to a configuration
array by convention — append \Module to the namespace, instantiate it, and ask it for its
config.
The package intentionally ships no concrete module. Your application provides its own
Vendor\Package\Module class extending AbstractModule, returning whatever that module
contributes (routes, services, view paths, and so on).
- Documentation: https://framework.jinexus.com/documentation
- Issues: https://github.com/jinexus-framework/jinexus-module-manager/issues
- PHP
^8.5
Install via Composer:
composer require jinexus-framework/jinexus-module-manageruse JiNexus\ModuleManager\ModuleManager\ModuleManager;
use JiNexus\ModuleManager\ModuleManager\Factory\ModuleManagerFactory;
$manager = new ModuleManager();
// ...or via the factory (a fresh, independent instance each call).
$manager = ModuleManagerFactory::build();Modules are registered as namespace strings, not class names or objects:
$manager->setModules(['Acme\Blog', 'Acme\Shop']);
$manager->getModules(); // ['Acme\Blog', 'Acme\Shop']
$manager->addModule('Acme\Wiki'); // true — appended
$manager->addModule('Acme\Wiki'); // false — already registeredTwo things about setModules() are worth knowing up front, because they differ from a
conventional setter:
$manager->setModules(['Acme\Blog']);
$manager->setModules(['Acme\Shop']);
$manager->getModules(); // ['Acme\Blog', 'Acme\Shop'] — it appends, it does not replace
$manager->setModules([]); // a no-op, NOT a reset
$manager->setModules(['blog' => 'Acme\Blog']);
$manager->getModules(); // keys are discarded; the list is re-indexedsetModules() does not deduplicate — only addModule() checks for an existing entry, and it
reports whether the module was actually added.
Extend AbstractModule and override getConfig(). The class must be named Module and sit
directly under the namespace you register:
namespace Acme\Blog;
use JiNexus\ModuleManager\ModuleManager\AbstractModule;
class Module extends AbstractModule
{
public function getConfig(): array
{
return [
'name' => 'blog',
'routes' => ['blog' => ['route' => '/blog']],
];
}
}AbstractModule::getConfig() returns [], so a module that overrides nothing is valid and
simply contributes no configuration.
$manager->getConfig('Acme\Blog');
// instantiates Acme\Blog\Module and returns its getConfig() resultThe argument is the namespace above the module class — \Module is appended for you.
Resolution is independent of registration: a module does not have to be added to the manager
before its config can be read.
foreach ($manager->getModules() as $module) {
$config = $manager->getConfig($module);
// merge it into your application config however your app prefers
}The manager returns each module's config as-is; merging, validating, and caching are left to the consuming application.
Package-level failures throw JiNexus\ModuleManager\ModuleManagerException (a subclass of
\Exception):
$manager->getConfig(); // ModuleManagerException: Module is required
$manager->getConfig(''); // ModuleManagerException: Module is requiredAn unsupported magic getter/setter resolved through AbstractBase::__call also throws a
ModuleManagerException with a Not implemented: … message.
An unresolvable namespace also throws a ModuleManagerException:
$manager->getConfig('No\Such\Vendor');
// ModuleManagerException: Module class "No\Such\Vendor\Module" cannot be resolvedVersion 1.1.0 raises the PHP floor to ^8.5 and renames the package exception:
// 1.0
use JiNexus\ModuleManager\Exception;
// 1.1
use JiNexus\ModuleManager\ModuleManagerException;It also adds parameter and return types across the public API, so if you implement
ModuleInterface/ModuleManagerInterface or extend AbstractModule/AbstractModuleManager,
your overrides need matching declarations — notably getConfig(): array. See
CHANGELOG.md for the full upgrade notes.
ModuleManager is a deliberately empty subclass of AbstractModuleManager — all behavior
lives on the abstract so the concrete class stays a stable extension point. Extend
AbstractModuleManager when you want to change registry behavior and extend
AbstractModule for your application's modules.
ModuleManagerInterface declares getModules() and getConfig() as mixed;
AbstractModuleManager narrows both to array. Implementations may narrow further.
composer install
composer test # or: ./vendor/bin/phpunit
composer test:coverage # text coverage report
composer test:testdox # readable, per-test outputphpunit.dist.xml is the committed configuration. Use XDEBUG_MODE=off to silence the local
Xdebug notice:
XDEBUG_MODE=off ./vendor/bin/phpunit --testdoxPlease see CONDUCT.md for the code of conduct. Contributions should include
tests and a CHANGELOG.md entry. See AGENTS.md for detailed build, style, and
workflow conventions.
BSD-3-Clause. See LICENSE.md.