JMVC
Wordpress MVC framework
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/snakeo/jmvc/archive/refs/heads/master.zipReadme
JMVC
A WordPress MVC Framework for Building Structured Applications
JMVC brings the Model-View-Controller pattern to WordPress, enabling developers to build organized, maintainable applications with clean separation of concerns. Built with support for AJAX routing, Advanced Custom Fields integration, and hierarchical modular architecture (HMVC).
Why JMVC?
Traditional WordPress development often leads to:
| Problem | Traditional WordPress | With JMVC |
|---|---|---|
| Code Organization | Logic scattered across functions.php, templates, random includes | Controllers, Models, Views in designated directories |
| Routing | Tied to permalink structure or manual rewrites | Clean URLs: /controller/pub/Task/show/42 |
| Business Logic | Mixed into theme templates | Isolated in Controllers and Models |
| Data Access | Direct database calls or scattered queries | Models with built-in WordPress post type integration |
| API Development | Repetitive REST API boilerplate | APIController with api_success() / api_die() |
| Testability | Tightly coupled to WordPress globals | Isolated classes, mockable dependencies |
| Onboarding | Every project organized differently | Standard MVC structure developers already know |
JMVC gives you Laravel-like structure while keeping everything WordPress:
- Custom Post Types become Models with magic property access
- ACF fields accessible as
$model->field_name - WordPress hooks, filters, and APIs still available
- Theme header/footer integration via Page Controllers
- Gutenberg blocks powered by PHP controllers
Table of Contents
- Why JMVC?
- Features
- Requirements
- Installation
- Admin Dashboard
- Quick Start
- Architecture Overview
- Core Components
- Routing
- Page Controllers
- Gutenberg Blocks
- REST API
- Security Features
- Environment Configuration
- Sample Application: Task Manager
- Developer Tools
- HMVC Modules
- API Reference
- Testing
- Contributing
- License
Features
- MVC Architecture - Clean separation of Models, Views, and Controllers
- WordPress Plugin - Install once, use in any theme
- Admin Dashboard - Initialize, configure, and manage via WordPress admin
- WordPress Integration - Native support for custom post types and WordPress APIs
- ACF Integration - Seamless Advanced Custom Fields support via traits
- AJAX Routing - Built-in URL routing through WordPress AJAX handlers
- REST API Support - Modern REST API endpoints alongside AJAX routing
- HMVC Support - Build modular, self-contained components
- API Development - Ready-to-use base controller for JSON APIs
- Developer Tools - Logging (JLog) and error alerting (DevAlert) built-in
- Key-Value Store - Redis or SQLite backend for caching and sessions
- Flexible Configuration - GUI-based config management with nested access
- Security Built-in - Nonce verification, CSRF protection, input sanitization, and output escaping
Requirements
- PHP 8.0 or higher (8.1+ recommended)
- WordPress 6.0 or higher
- Composer for dependency management
Dependencies
- Predis ^2.0 - Redis client (optional)
Optional (Recommended)
- Advanced Custom Fields (ACF) - For model field management
- Redis or SQLite - For kvstore backend
Installation
1. Install the Plugin
Option A: Download
- Download the latest release from GitHub
- Extract to
/wp-content/plugins/jmvc/
Option B: Clone
cd /path/to/wordpress/wp-content/plugins/
git clone https://github.com/your-repo/jmvc.git
2. Activate the Plugin
- Go to Plugins in WordPress admin
- Find "JMVC" and click Activate

3. Initialize JMVC in Your Theme
- Go to JMVC > Dashboard in the admin menu
- Click Initialize JMVC to create the scaffolding in your active theme
- Click Install Dependencies to run Composer (or follow manual instructions if shell access is unavailable)

4. Flush Permalinks
JMVC uses WordPress's native Rewrite API - no manual server configuration needed.
If routes aren't working after activation:
- Go to Settings > Permalinks
- Click Save Changes (this flushes rewrite rules)
That's it! Routes like /controller/pub/Task/index will work automatically on any server.
Admin Dashboard
JMVC provides a full admin interface for managing your application.
Dashboard (JMVC > Dashboard)
The main dashboard shows:
- Theme Status - Active theme name and JMVC initialization status
- Dependencies - Composer vendor folder status with install button
- Rewrite Rules - Auto-test with link to flush permalinks if needed
- Component Counts - Number of controllers, models, and views
Actions:
- Initialize JMVC - Creates scaffolding directories in your theme
- Install Dependencies - Runs
composer install(or shows manual instructions) - Test Rewrite - Re-checks if WordPress rewrite rules are active
Settings (JMVC > Settings)
Configure JMVC options via UI:
Developer Alerts
- Email address for error notifications
- Slack webhook URL, channel, and bot username
Key-Value Store
- Storage type (SQLite or Redis)
Settings are saved to PHP config files in your theme's jmvc/config/ directory.

Components Browser (JMVC > Components)
Browse all your MVC components:
- Controllers Tab - View public, admin, and resource controllers
- Models Tab - View all models
- Views Tab - Browse view templates in a tree structure

Quick Start
Create Your First Controller
After initializing JMVC, create a controller in your theme:
<?php
// {theme}/jmvc/controllers/pub/HelloController.php
class HelloController {
/**
* Basic action - outputs text
* URL: /controller/pub/Hello/index
*/
public function index() {
echo "Hello, JMVC!";
}
/**
* Action with parameter
* URL: /controller/pub/Hello/greet/John
*/
public function greet($name) {
echo "Hello, " . esc_html($name) . "!";
}
/**
* Render a view
* URL: /controller/pub/Hello/welcome
*/
public function welcome() {
$data = [
'title' => 'Welcome to JMVC',
'message' => 'Build WordPress apps with MVC!'
];
JView::show('hello/welcome', $data);
}
}
Create a View
<?php // {theme}/jmvc/views/hello/welcome.php ?>
<!DOCTYPE html>
<html>
<head>
<title><?= esc_html($title) ?></title>
</head>
<body>
<h1><?= esc_html($title) ?></h1>
<p><?= esc_html($message) ?></p>
</body>
</html>
Access Your Controller
Visit these URLs (adjust domain as needed):
https://yoursite.com/controller/pub/Hello/indexhttps://yoursite.com/controller/pub/Hello/greet/Worldhttps://yoursite.com/controller/pub/Hello/welcome
Or use the REST API:
https://yoursite.com/wp-json/jmvc/v1/pub/Hello/index
Architecture Overview
Directory Structure
JMVC splits between the plugin (framework core) and your theme (application code):
/wp-content/plugins/jmvc/ # Framework Core (Plugin)
├── jmvc.php # Plugin entry point
├── system/ # Core framework classes
│ ├── boot.php # Bootstrap
│ ├── JBag.php # Service locator
│ ├── config/JConfig.php # Configuration manager
│ ├── controller/
│ │ ├── JController.php # Controller loader
│ │ └── JControllerAjax.php # AJAX routing
│ ├── model/
│ │ ├── JModel.php # Model loader
│ │ ├── JModelBase.php # Base model class
│ │ └── ACFModelTrait.php # ACF integration
│ ├── view/JView.php # View renderer
│ ├── routing/ # WordPress Rewrite API routing
│ │ ├── JRouter.php # Rewrite rule registration
│ │ └── JPageController.php # Page controller base class
│ ├── blocks/ # Gutenberg block system
│ │ ├── JBlock.php # Block registration
│ │ └── JBlockController.php # Block controller base class
│ └── app/dev/
│ ├── JLog.php # Logging
│ └── DevAlert.php # Error alerts
├── admin/ # Admin panel
│ ├── Admin.php # Menu & AJAX handlers
│ ├── Installer.php # Scaffolding installer
│ ├── ConfigWriter.php # Config file generator
│ ├── Browser.php # Component scanner
│ ├── RewriteTest.php # Rewrite tester
│ ├── views/ # Admin templates
│ └── assets/ # Admin CSS/JS
├── controllers/pub/
│ └── JmvcController.php # Health check endpoint
└── assets/js/global.js.php # JavaScript helpers
/wp-content/themes/{your-theme}/jmvc/ # Your Application (Theme)
├── controllers/ # MVC Controllers
│ ├── pub/ # Public/frontend controllers
│ ├── admin/ # Admin-only controllers
│ └── resource/ # Resource/API controllers
├── models/ # MVC Models
├── views/ # MVC Views (templates)
│ └── blocks/ # Block view templates
├── libraries/ # Reusable service classes
├── modules/ # HMVC modules (optional)
├── config/ # Configuration files
│ ├── devalert.php # Alert settings
│ ├── kvstore.php # Key-value store config
│ └── blocks.php # Gutenberg block registrations
├── templates/ # Page templates (for JView::showPage)
├── composer.json # Dependencies
└── vendor/ # Composer packages
Request Flow
┌─────────────────────────────────────────────────────────────────┐
│ HTTP Request │
│ /controller/pub/Task/show/123 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ WordPress AJAX Handler │
│ wp_ajax_pub_controller │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ JControllerAjax │
│ Parses URL: env=pub, controller=Task, │
│ function=show, params=[123] │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ JController │
│ Loads {theme}/jmvc/controllers/pub/TaskController.php │
│ Instantiates TaskController │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TaskController │
│ $controller->show(123) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ JModel │ │ JView │ │ Response │ │
│ │ Load Task │───▶│ Render HTML │───▶│ Output │ │
│ │ Model │ │ or JSON │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Core Components
Controllers
Controllers handle incoming requests and coordinate between models and views.
Loading Controllers
// Load a controller manually (rarely needed - routing handles this)
$controller = JController::load('Task', 'pub');
$controller->index();
// With HMVC module
$controller = JController::load('Task', 'pub', 'mymodule');
Controller Environments
| Environment | Directory | WordPress Hook | Use Case |
|---|---|---|---|
pub |
controllers/pub/ |
wp_ajax_pub_controller, wp_ajax_nopriv_pub_controller |
Public endpoints (logged in or not) |
admin |
controllers/admin/ |
wp_ajax_admin_controller |
Admin-only endpoints |
resource |
controllers/resource/ |
wp_ajax_resource_controller, wp_ajax_nopriv_resource_controller |
Static resources, files |