JiNexus MVC is a minimal, component-based MVC kernel for PHP 8.5+. It provides a
request–dispatch–render pipeline by wiring together several JiNexus components:
- Route — URI matching against a named route table
- Config — merged module configuration
- Http — request/response abstraction
- ModuleManager — module loading and config aggregation
The framework is deliberately unopinionated beyond the pipeline shape. Controllers, views, and models are plain PHP objects that implement the provided interfaces.
- Documentation: https://framework.jinexus.com/documentation
- Issues: https://github.com/jinexus-framework/jinexus-mvc/issues
- PHP
^8.5 jinexus-framework/jinexus-config^1.1jinexus-framework/jinexus-http^1.1jinexus-framework/jinexus-module-manager^1.1jinexus-framework/jinexus-route^1.1
Install via Composer:
composer require jinexus-framework/jinexus-mvcuse JiNexus\Mvc\Application\Factory\ApplicationFactory;
$app = ApplicationFactory::build([
'modules' => [
App\Module::class,
],
]);
$app->run();Each module class provides a getConfig(): array method that returns its routes and
view configuration. The application factory aggregates all module configs via
array_merge_recursive and passes the result to the pipeline:
namespace App;
class Module
{
public function getConfig(): array
{
return [
'routes' => [
'home' => [
'route' => '/',
'controller' => 'App\Controller\IndexController',
'action' => 'index',
],
],
'view_manager' => [
'template_map' => [
'layout/layout' => 'module/Application/view/layout.phtml',
'error/404' => 'module/Application/view/error/404.phtml',
],
'template_path_stack' => ['module/Application/view'],
],
];
}
}Controllers extend AbstractController and implement action methods suffixed with
Action. Each action can return void (no view variables) or a ViewModel:
namespace App\Controller;
use JiNexus\Mvc\Controller\AbstractController;
use JiNexus\Mvc\Model\ViewModel;
class IndexController extends AbstractController
{
public function indexAction()
{
// Reads $this->request, $this->http, $this->view, $this->redirect
}
public function jsonAction()
{
return new ViewModel(['key' => 'value']);
}
}Controller actions have access to:
| Property | Type | Source |
|---|---|---|
$this->view |
ViewInterface |
The application's view |
$this->http |
HttpInterface |
The application's HTTP container |
$this->request |
RequestInterface |
From $this->http->request |
$this->redirect |
RedirectInterface |
From the application's route redirect |
View is a variable bag with PHTML rendering. Use it directly or via the
application's $app->view:
$view->set('title', 'Hello');
$view->get('title'); // 'Hello'
$view->has('title'); // true
$view->get('missing', 'fallback'); // 'fallback'
$view->add(['key' => 'val']); // merge
$view->remove('title'); // delete
$html = $view->render('path/to/template.phtml');When $app->run() completes, the configured layout template is rendered with all view
variables extracted into scope.
The run() method executes these steps:
- View dispatch —
dispatchView()creates aViewbound to the application. - Route match — If no route matches the current URI, 404 headers are sent and the application terminates.
- Controller dispatch —
dispatchController()instantiates the matched controller. - Action dispatch —
dispatchAction($controller)calls the matched action method. - View render —
renderView()renders the configured layout template.
$app->matchRoute; // array — the matched route, or [] on 404
$app->namespace; // string — controller FQCN
$app->moduleName; // string — first namespace segment
$app->controllerName; // string — last namespace segment
$app->actionName; // string — the matched actionAll pipeline properties are read-only (PHP 8.5 property hooks).
PHP errors are converted to ErrorException instances via the
AbstractApplication::error() static method, which is registered as the error handler
during ApplicationFactory::build().
Package-level failures throw JiNexus\Mvc\MvcException (a subclass of \Exception).
composer install
composer test # or: ./vendor/bin/phpunit
composer test:coverage # text coverage reportphpunit.dist.xml is the committed configuration. Use XDEBUG_MODE=off to silence the
local Xdebug notice, and --testdox for readable output:
XDEBUG_MODE=off ./vendor/bin/phpunit --testdoxApplication, View, and factory classes are deliberately empty subclasses of their
abstract parents. Keep them that way — the public accessors are implemented with PHP
property hooks over backing fields, and declaring a real property would shadow them.
For IDE autocompletion, prefer @property PHPDoc tags over real properties.
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.
BSD-3-Clause. See LICENSE.md.