jinexus-framework / jinexus-module-manager
Module Manager component from JiNexus Framework
Package info
github.com/jinexus-framework/jinexus-module-manager
Type:component
pkg:composer/jinexus-framework/jinexus-module-manager
Requires
- php: ^8.5
Requires (Dev)
- phpunit/phpunit: ^13.2
This package is auto-updated.
Last update: 2026-07-29 19:23:01 UTC
README
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
Requirements
- PHP
^8.5
Installation
Install via Composer:
composer require jinexus-framework/jinexus-module-manager
Usage
Creating a module manager
use 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();
Registering modules
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 registered
Two 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-indexed
setModules() does not deduplicate — only addModule() checks for an existing entry, and it
reports whether the module was actually added.
Writing a module
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.
Reading a module's config
$manager->getConfig('Acme\Blog'); // instantiates Acme\Blog\Module and returns its getConfig() result
The 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.
Error handling
Package-level failures throw JiNexus\ModuleManager\ModuleManagerException (a subclass of
\Exception):
$manager->getConfig(); // ModuleManagerException: Module is required $manager->getConfig(''); // ModuleManagerException: Module is required
An 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 resolved
Upgrading from 1.0.0
Version 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.
Extending
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.
Testing
composer install composer test # or: ./vendor/bin/phpunit composer test:coverage # text coverage report composer test:testdox # readable, per-test output
phpunit.dist.xml is the committed configuration. Use XDEBUG_MODE=off to silence the local
Xdebug notice:
XDEBUG_MODE=off ./vendor/bin/phpunit --testdox
Contributing
Please 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.
License
BSD-3-Clause. See LICENSE.md.