neuron-php / mvc
MVC manager.
Requires
- php: ^8.4
- ext-curl: *
- ext-json: *
- league/commonmark: ^2.6
- neuron-php/application: 0.7.*
- neuron-php/cli: 0.1.*
- neuron-php/routing: ^0.6.8
Requires (Dev)
- mikey179/vfsstream: ^1.6
- phpmd/phpmd: ^2.15
- phpunit/phpunit: 9.*
- dev-master
- 0.7.2
- 0.7.1
- 0.7.0
- 0.6.48
- 0.6.47
- 0.6.46
- 0.6.45
- 0.6.44
- 0.6.43
- 0.6.42
- 0.6.41
- 0.6.40
- 0.6.39
- 0.6.38
- 0.6.37
- 0.6.36
- 0.6.35
- 0.6.34
- 0.6.33
- 0.6.32
- 0.6.31
- 0.6.30
- 0.6.29
- 0.6.28
- 0.6.27
- 0.6.26
- 0.6.24
- 0.6.23
- 0.6.22
- 0.6.21
- 0.6.20
- 0.6.19
- 0.6.18
- 0.6.17
- 0.6.16
- 0.6.15
- 0.6.14
- 0.6.13
- 0.6.12
- 0.6.11
- 0.6.10
- 0.6.9
- 0.6.8
- 0.6.7
- 0.6.6
- 0.6.5
- 0.6.4
- 0.6.3
- 0.6.2
- 0.6.1
- 0.6.0
- 0.5.5
- 0.5.4
- 0.5.3
- 0.5.2
- 0.5.1
- 0.5.0
- dev-develop
This package is auto-updated.
Last update: 2025-08-28 21:22:40 UTC
README
Neuron-PHP MVC
A lightweight MVC (Model-View-Controller) framework component for PHP 8.4+ that provides core MVC functionality including controllers, views, routing integration, request handling, and a powerful view caching system.
Table of Contents
- Installation
- Quick Start
- Core Components
- Configuration
- Usage Examples
- Advanced Features
- CLI Commands
- API Reference
- Testing
- More Information
Installation
Requirements
- PHP 8.4 or higher
- Composer
Install via Composer
Install php composer from https://getcomposer.org/
Install the neuron MVC component:
composer require neuron-php/mvc
Quick Start
1. Create the Front Controller
Create a public/index.php
file:
<?php require_once '../vendor/autoload.php'; // Bootstrap the application $app = boot('../config'); // Dispatch the current request dispatch($app);
2. Configure Apache (.htaccess)
Create a public/.htaccess
file to route all requests through the front controller:
IndexIgnore * Options +FollowSymlinks RewriteEngine on # Redirect all requests to index.php # except for actual files and directories RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
For Nginx
If using Nginx, add this to your server configuration:
location / { try_files $uri $uri/ /index.php?route=$uri&$args; }
3. Minimal Configuration
Create a config/config.yaml
file:
system: base_path: . routes_path: config views: path: resources/views
Create a config/routes.yaml
file:
routes: home: route: / method: GET controller: App\Controllers\HomeController@index
Core Components
Application
The main application class (Neuron\Mvc\Application
) handles:
- Route configuration loading from YAML files
- Request routing and controller execution
- Event dispatching for HTTP errors
- Output capture for testing
- Cache management
Controllers
Controllers handle incoming requests and return responses. All controllers should extend Neuron\Mvc\Controllers\Base
and implement the IController
interface.
namespace App\Controllers; use Neuron\Mvc\Controllers\Base; use Neuron\Mvc\Responses\HttpResponseStatus; class HomeController extends Base { public function index(): string { return $this->renderHtml( HttpResponseStatus::OK, ['title' => 'Welcome'], 'index', // view file 'default' // layout file ); } }
Available render methods:
renderHtml()
- Render HTML views with layoutsrenderJson()
- Return JSON responsesrenderXml()
- Return XML responsesrenderMarkdown()
- Render Markdown content with CommonMark
Views
Views support multiple formats and are stored in the configured views directory:
HTML Views
// resources/views/home/index.php <h1><?php echo $title; ?></h1>
Layouts
// resources/views/layouts/default.php <!DOCTYPE html> <html> <head> <title><?php echo $title ?? 'My App'; ?></title> </head> <body> <?php echo $Content; ?> </body> </html>
Routing
Routes are defined in YAML files and support various HTTP methods:
routes: user_profile: route: /user/{id} method: GET controller: App\Controllers\UserController@profile request: user_profile # optional request validation api_users: route: /api/users method: POST controller: App\Controllers\Api\UserController@create
Request Handling
Create request parameter definitions for validation:
# config/requests/user_profile.yaml parameters: id: type: integer required: true min_value: 1
Access parameters in controllers:
public function profile(Request $request): string { $userId = $request->getParam('id')->getValue(); // ... }
URL Helpers
The framework provides Rails-style URL helpers for generating URLs from named routes. This makes it easy to generate consistent URLs throughout your application.
Route Naming
Routes are automatically named based on their configuration key in the YAML file:
routes: user_profile: # This becomes the route name route: /users/{id} method: GET controller: App\Controllers\UserController@profile admin_user_posts: route: /admin/users/{user_id}/posts/{post_id} method: GET controller: App\Controllers\AdminController@userPosts
Using URL Helpers in Controllers
Controllers can use URL helpers directly via magic methods:
class UserController extends Base { public function show($id): string { $user = User::find($id); // Magic methods for URL generation $editUrl = $this->userEditPath(['id' => $id]); $absoluteUrl = $this->userProfileUrl(['id' => $id]); // Use in redirects if (!$user) { return redirect($this->userIndexPath()); } return $this->renderHtml(HttpResponseStatus::OK, [ 'user' => $user, 'edit_url' => $editUrl ]); } public function create(): string { // After creating user, redirect using magic method $user = new User($request->all()); $user->save(); return redirect($this->userProfilePath(['id' => $user->id])); } }
Direct URL Helper Methods
Controllers also provide direct helper methods:
// Generate relative URLs $profileUrl = $this->urlFor('user_profile', ['id' => 123]); // Generate absolute URLs $absoluteUrl = $this->urlForAbsolute('user_profile', ['id' => 123]); // Check if route exists if ($this->routeExists('user_profile')) { // Route is available } // Get UrlHelper instance for advanced usage $urlHelper = $this->urlHelper();
Using URL Helpers in Views
URL helpers are automatically available in all views through the injected $urlHelper
variable:
<!-- resources/views/user/profile.php --> <div class="user-profile"> <h1><?= $user->name ?></h1> <!-- Magic methods in views --> <a href="<?= $urlHelper->userEditPath(['id' => $user->id]) ?>" class="btn">Edit</a> <a href="<?= $urlHelper->userPostsPath(['user_id' => $user->id]) ?>" class="btn">View Posts</a> <!-- Complex routes work too --> <a href="<?= $urlHelper->adminUserReportsPath(['id' => $user->id, 'year' => date('Y')]) ?>"> Admin Reports </a> <!-- Direct method calls --> <a href="<?= $urlHelper->routePath('user_profile', ['id' => $user->id]) ?>">Profile</a> <a href="<?= $urlHelper->routeUrl('user_profile', ['id' => $user->id]) ?>">Share Link</a> </div>
Magic Method Conventions
The magic methods follow Rails naming conventions:
Route Name in YAML | Magic Method (Relative) | Magic Method (Absolute) | Generated URL |
---|---|---|---|
user_profile |
userProfilePath() |
userProfileUrl() |
/users/123 |
user_edit |
userEditPath() |
userEditUrl() |
/users/123/edit |
admin_user_posts |
adminUserPostsPath() |
adminUserPostsUrl() |
/admin/users/1/posts/2 |
blog_category |
blogCategoryPath() |
blogCategoryUrl() |
/blog/category/tech |
URL Helper Methods
Method | Description | Example |
---|---|---|
routePath($name, $params) |
Generate relative URL | $urlHelper->routePath('user_profile', ['id' => 123]) |
routeUrl($name, $params) |
Generate absolute URL | $urlHelper->routeUrl('user_profile', ['id' => 123]) |
routeExists($name) |
Check if route exists | $urlHelper->routeExists('user_profile') |
getAvailableRoutes() |
List all named routes | $urlHelper->getAvailableRoutes() |
{routeName}Path($params) |
Magic method for relative URL | $urlHelper->userProfilePath(['id' => 123]) |
{routeName}Url($params) |
Magic method for absolute URL | $urlHelper->userProfileUrl(['id' => 123]) |
Error Handling
URL helpers gracefully handle missing routes:
// Returns null if route doesn't exist $url = $urlHelper->nonExistentRoutePath(['id' => 123]); if ($url === null) { // Handle missing route $url = $urlHelper->userIndexPath(); // fallback }
Advanced Usage
// Get all available routes for debugging $routes = $urlHelper->getAvailableRoutes(); foreach ($routes as $route) { echo "Route: {$route['name']} -> {$route['method']} {$route['path']}\n"; } // Custom UrlHelper instance $customHelper = new UrlHelper($customRouter);
Configuration
All YAML config file parameters can be overridden by environment variables in the form of <CATEGORY>_<KEY>
, e.g.
SYSTEM_BASE_PATH
.
Main Configuration (config.yaml)
# System settings system: timezone: US/Eastern base_path: . routes_path: config # View settings views: path: resources/views # Logging logging: destination: \Neuron\Log\Destination\File format: \Neuron\Log\Format\PlainText file: app.log level: debug # Cache configuration cache: enabled: true storage: file path: cache/views ttl: 3600 # Default TTL in seconds html: true # Enable HTML view caching markdown: true # Enable Markdown view caching json: false # Disable JSON response caching xml: false # Disable XML response caching # Garbage collection settings (optional) gc_probability: 0.01 # 1% chance to run GC on cache write gc_divisor: 100 # Fine-tune probability calculation
Cache Configuration Options
Option | Description | Default |
---|---|---|
enabled |
Enable/disable caching globally | true |
storage |
Storage type (currently only 'file') | file |
path |
Directory for cache files | cache/views |
ttl |
Default time-to-live in seconds | 3600 |
views.* |
Enable caching per view type | varies |
gc_probability |
Probability of running garbage collection | 0.01 |
gc_divisor |
Divisor for probability calculation | 100 |
Usage Examples
Creating a Controller
namespace App\Controllers; use Neuron\Mvc\Controllers\Base; use Neuron\Mvc\Requests\Request; use Neuron\Mvc\Responses\HttpResponseStatus; class ProductController extends Base { public function list(): string { $products = $this->getProducts(); return $this->renderHtml( HttpResponseStatus::OK, ['products' => $products], 'list', 'default' ); } public function apiList(): string { $products = $this->getProducts(); return $this->renderJson( HttpResponseStatus::OK, ['products' => $products] ); } public function details(Request $request): string { $id = $request->getParam('id')->getValue(); $product = $this->getProduct($id); if (!$product) { return $this->renderHtml( HttpResponseStatus::NOT_FOUND, ['message' => 'Product not found'], 'error', 'default' ); } return $this->renderHtml( HttpResponseStatus::OK, ['product' => $product], 'details', 'default' ); } }
Request Parameter Validation
Define parameters in YAML:
# config/requests/product_create.yaml parameters: name: type: string required: true min_length: 3 max_length: 100 price: type: currency required: true min_value: 0 category_id: type: integer required: true description: type: string required: false max_length: 1000
Available parameter types:
string
,integer
,float
,boolean
email
,url
,uuid
date
,datetime
currency
,phone_number
array
,object
Error Handling
The framework automatically handles 404 errors:
// Custom 404 handler class NotFoundController extends HttpCodes { public function render404(): string { return $this->renderHtml( HttpResponseStatus::NOT_FOUND, ['message' => 'Page not found'], '404', 'error' ); } }
Advanced Features
View Caching
The framework includes a sophisticated view caching system:
- Automatic Cache Key Generation: Based on controller, view, and data
- Selective Caching: Enable/disable per view type
- TTL Support: Configure expiration times
- Garbage Collection: Automatic cleanup of expired entries
// Cache is automatically used when enabled $html = $this->renderHtml( HttpResponseStatus::OK, $data, 'cached-view', 'layout' );
Manual Cache Management
// Clear all expired cache entries $removed = ClearExpiredCache($app); echo "Removed $removed expired cache entries"; // Clear all cache $app->getViewCache()->clear();
You can also manage cache using the CLI commands. See CLI Commands section for details.
Custom View Implementations
Create custom view types by implementing IView
:
namespace App\Views; use Neuron\Mvc\Views\IView; class PdfView implements IView { public function render(array $Data): string { // Generate PDF content return $pdfContent; } }
Event System
Listen for HTTP events:
# config/events.yaml listeners: http_404: class: App\Listeners\NotFoundLogger method: logNotFound
CLI Commands
The MVC component includes several CLI commands for managing cache and routes. These commands are available when using the Neuron CLI tool.
Cache Management Commands
mvc:cache:clear
Clear view cache entries.
Options:
--type, -t VALUE
- Clear specific cache type (html, json, xml, markdown)--expired, -e
- Only clear expired entries--force, -f
- Clear without confirmation--config, -c PATH
- Path to configuration directory
Examples:
# Clear all cache entries (with confirmation) neuron mvc:cache:clear # Clear only expired entries neuron mvc:cache:clear --expired # Clear specific cache type neuron mvc:cache:clear --type=html # Force clear without confirmation neuron mvc:cache:clear --force # Specify custom config path neuron mvc:cache:clear --config=/path/to/config
mvc:cache:stats
Display comprehensive cache statistics.
Options:
--config, -c PATH
- Path to configuration directory--json, -j
- Output statistics in JSON format--detailed, -d
- Show detailed breakdown by view type
Examples:
# Display cache statistics neuron mvc:cache:stats # Show detailed statistics with view type breakdown neuron mvc:cache:stats --detailed # Output as JSON for scripting neuron mvc:cache:stats --json # Detailed JSON output neuron mvc:cache:stats --detailed --json
Sample Output:
MVC View Cache Statistics
==================================================
Configuration:
Cache Path: /path/to/cache/views
Cache Enabled: Yes
Default TTL: 3600 seconds (1 hour)
Overall Statistics:
Total Cache Entries: 247
Valid Entries: 189
Expired Entries: 58
Total Cache Size: 2.4 MB
Average Entry Size: 10.2 KB
Oldest Entry: 2025-08-10 14:23:15
Newest Entry: 2025-08-13 09:45:32
Recommendations:
- 58 expired entries can be cleared (saving ~580 KB)
Run: neuron mvc:cache:clear --expired
Route Management Commands
mvc:routes:list
List all registered routes with filtering options.
Options:
--config, -c PATH
- Path to configuration directory--controller VALUE
- Filter by controller name--method, -m VALUE
- Filter by HTTP method (GET, POST, PUT, DELETE, etc.)--pattern, -p VALUE
- Search routes by pattern--json, -j
- Output routes in JSON format
Examples:
# List all routes neuron mvc:routes:list # Filter by controller neuron mvc:routes:list --controller=UserController # Filter by HTTP method neuron mvc:routes:list --method=POST # Search by pattern neuron mvc:routes:list --pattern=/api/ # Combine filters neuron mvc:routes:list --controller=Api --method=GET # Output as JSON for processing neuron mvc:routes:list --json
Sample Output:
MVC Routes
======================================================================================
Name | Pattern | Method | Controller | Action
--------------------------------------------------------------------------------------
home | / | GET | HomeController | index
user_profile | /user/{id} | GET | UserController | profile
api_users_list | /api/users | GET | Api\UserController | list
api_users_create | /api/users | POST | Api\UserController | create
products_list | /products | GET | ProductController | list
product_details | /products/{id} | GET | ProductController | details
Total routes: 6
Named routes: 6
Methods: GET: 4, POST: 2
API Reference
Bootstrap Functions
Boot(string $ConfigPath): Application
Initialize the application with configuration.
$app = Boot('/path/to/config');
Dispatch(Application $App): void
Process the current HTTP request.
Dispatch($app);
ClearExpiredCache(Application $App): int
Remove expired cache entries.
$removed = ClearExpiredCache($app);
Key Interfaces
IController
All controllers must implement this interface:
renderHtml()
- Render HTML with layoutrenderJson()
- Render JSON responserenderXml()
- Render XML response
IView
Views must implement:
render(array $Data): string
- Render the view
ICacheStorage
Cache storage implementations must provide:
read()
,write()
,exists()
,delete()
clear()
- Clear all entriesisExpired()
- Check expirationgc()
- Garbage collection
Testing
Run the test suite:
# Run all tests vendor/bin/phpunit -c tests/phpunit.xml # Run with coverage vendor/bin/phpunit -c tests/phpunit.xml --coverage-html coverage # Run specific test file vendor/bin/phpunit -c tests/phpunit.xml tests/Mvc/ApplicationTest.php
More Information
You can read more about the Neuron components at neuronphp.com