jinexus-framework / jinexus-mvc
MVC component from JiNexus Framework
Package info
github.com/jinexus-framework/jinexus-mvc
Type:component
pkg:composer/jinexus-framework/jinexus-mvc
Requires
- php: ^8.5
- filp/whoops: ^2.18
- jinexus-framework/jinexus-config: ^1.1
- jinexus-framework/jinexus-http: ^1.1
- jinexus-framework/jinexus-module-manager: ^1.1
- jinexus-framework/jinexus-route: ^1.1
Requires (Dev)
- phpunit/phpunit: ^13.2
This package is auto-updated.
Last update: 2026-07-29 19:46:27 UTC
README
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
Requirements
- 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
Installation
Install via Composer:
composer require jinexus-framework/jinexus-mvc
Quick start
use JiNexus\Mvc\Application\Factory\ApplicationFactory; $app = ApplicationFactory::build([ 'modules' => [ App\Module::class, ], ]); $app->run();
Module configuration
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'], ], ]; } }
Creating a controller
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 |
The view layer
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 application pipeline
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.
Accessing pipeline properties
$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 action
All pipeline properties are read-only (PHP 8.5 property hooks).
Error handling
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).
Testing
composer install composer test # or: ./vendor/bin/phpunit composer test:coverage # text coverage report
phpunit.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 --testdox
Extending
Application, 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.
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.