Major version upgrade from 1.0.0 to 2.0.0 including copyright year updates, website URL migration to syspanel.com.br, and comprehensive CSRF token handling improvements. The Twig csrf() helper now returns a complete hidden input field instead of a raw token value, and token generation is now automatic when empty. Session initialization has been centralized in BaseController, and child controllers now properly call parent constructors. CRUD views have been modernized with flexbox layouts and consistent CSRF rendering. Documentation has been expanded with features, requirements, and project structure sections, and donation sections have been added across all pages.
10 KiB
Executable File
SysMVC
SysMVC is a lightweight PHP MVC framework created by Marco Costa (syspanel@gmx.com), licensed under the MIT License.
This software is free to use, modify, and distribute under the terms of the MIT License.
- Website: https://sysmvc.syspanel.com.br
- GitHub: https://github.com/syspanel/SysMVC
Features
- MVC Architecture — clean separation of concerns with Models, Views, and Controllers
- ORM (Eloquent) — database access via
illuminate/database(Laravel's Eloquent ORM) - Twin Template Engines — BladeOne and Twig, configured side by side
- Dependency Injection — PHP-DI container with autowiring
- Routing — flexible HTTP routing via Pecee SimpleRouter
- CSRF Protection — built-in token generation and validation
- Security Headers — applied automatically via
BaseController - Input/Output Sanitisation —
Sanitizerservice with email and URL awareness - CLI Console — Symfony Console commands for key generation and database migrations
- Logging — Monolog writes to
logs/app.log - Mail — Symfony Mailer integration
- Authentication — Delight Auth and PHP Auth libraries
Requirements
| Requirement | Version |
|---|---|
| PHP | >= 7.4 |
| Composer | latest stable |
| Web Server | Apache or Nginx |
| Database | MySQL 5.7+ |
Project Structure
app/
├── app/
│ ├── Controllers/ # HTTP controllers
│ ├── Models/ # Eloquent models
│ ├── Services/ # Shared services (BaseController, Sanitizer)
│ └── Console/Command/ # CLI console commands
├── bootstrap/
│ ├── app.php # Bootstrap: loads config, routes, container
│ ├── csrf.php # CSRF token helpers
│ └── helpers.php # Global helper functions
├── config/
│ ├── container.php # DI container definitions (Blade, Twig, Monolog)
│ ├── database.php # Eloquent ORM connection setup
│ ├── envread.php # .env loader (defines constants)
│ ├── paths.php # VIEWS_PATH and CACHE_PATH constants
│ └── templateengine.php # CSRF template helpers
├── database/
│ └── crudexample.sql # Sample SQL schema
├── routes/
│ ├── web.php # Web routes
│ ├── api.php # API routes (extend as needed)
│ └── auth.php # Auth routes (extend as needed)
├── resources/views/ # Blade and Twig template files
├── public/
│ └── index.php # Application entry point
├── storage/ # Uploads and generated files
├── cache/ # Compiled template cache
├── logs/ # Application log files
├── tests/
│ ├── Feature/ # Feature tests
│ └── Unit/ # Unit tests
├── bin/
│ └── console # CLI entry point
├── composer.json
└── .env # Environment configuration (gitignored)
Installation
1. Clone or unzip the project
unzip sysmvc.zip -d sysmvc
cd sysmvc
2. Install PHP dependencies
composer install
3. Configure the environment
cp .env.example .env
Edit .env with your database and application settings:
# Application
APP_NAME=SysMVC
APP_ENV=production
APP_DEBUG=false
APP_URL=http://localhost:16270
# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_password
4. Set directory permissions
chmod -R 775 storage
chmod -R 775 cache
chmod -R 775 logs
chmod -R 775 bootstrap/cache
5. Generate the application key
php bin/console generate:app-key
6. Set up the database
Create the database manually or run the sample migration command:
php bin/console migrate:crudexample
7. Configure the web server
Apache — add a virtual host pointing to the public/ directory:
<VirtualHost *:80>
ServerName sysmvc.local
DocumentRoot /path/to/sysmvc/public
<Directory /path/to/sysmvc/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Nginx — add a server block pointing to the public/ directory:
server {
listen 80;
server_name sysmvc.local;
root /path/to/sysmvc/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
CLI Commands
All CLI commands are available through the bin/console entry point:
php bin/console [command]
| Command | Description |
|---|---|
generate:app-key |
Generates a new APP_KEY and writes it to .env |
generate:api-keys |
Generates API_PUBLIC_KEY and API_SECRET_KEY in .env |
migrate:crudexample |
Creates the crudexample table with 30 sample records |
say:hello |
Example / demo command |
Routing
Routes are defined in routes/web.php using Pecee SimpleRouter syntax.
Example routes
Router::get('/', [HomeController::class, 'index'])->name('home');
Router::get('/about', function () { ... })->name('about');
Router::post('/crudexample', [CrudExampleController::class, 'store'])->name('crudexample.store');
Route groups
Router::group(['prefix' => '/crudexample'], function () {
Router::get('/', 'CrudExampleController@index')->name('crudexample.index');
Router::get('/create', 'CrudExampleController@create')->name('crudexample.create');
Router::get('/edit/{id}', 'CrudExampleController@edit')->name('crudexample.edit');
Router::post('/store', 'CrudExampleController@store')->name('crudexample.store');
Router::post('/update/{id}', 'CrudExampleController@update')->name('crudexample.update');
Router::post('/delete/{id}', 'CrudExampleController@delete')->name('crudexample.delete');
Router::get('/show/{id}', 'CrudExampleController@show')->name('crudexample.show');
});
404 errors are handled by a global error handler that renders resources/views/errors/404.html.
Security
SysMVC includes multiple security layers, all applied automatically.
Security Headers (BaseController)
Applied to every controller that extends BaseController:
| Header | Value |
|---|---|
Content-Security-Policy |
default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: |
X-Frame-Options |
DENY |
X-Content-Type-Options |
nosniff |
Referrer-Policy |
no-referrer |
Strict-Transport-Security |
max-age=31536000; includeSubDomains; preload |
CSRF Protection
Tokens are generated per session via generateCsrfToken() in bootstrap/csrf.php. Include the hidden field in forms with:
<?= csrf() ?>
<!-- or -->
<input type="hidden" name="csrf_token" value="<?= getCsrfToken() ?>">
Input Sanitisation
All form inputs are sanitised through Sanitizer::sanitizeInput() before storage. Output escaping is applied via Sanitizer::sanitizeOutput() before rendering.
Password Storage
Passwords are hashed with password_hash($password, PASSWORD_BCRYPT) before being persisted.
Environment Variables
Key environment variables loaded from .env:
| Variable | Default | Description |
|---|---|---|
APP_NAME |
SysMVC |
Application name |
APP_KEY |
— | Random encryption key |
APP_ENV |
production |
Environment: production / local / testing |
APP_DEBUG |
false |
Display error details |
APP_URL |
— | Base URL of the application |
DB_CONNECTION |
mysql |
Database driver |
DB_HOST |
127.0.0.1 |
Database host |
DB_PORT |
3306 |
Database port |
DB_DATABASE |
— | Database name |
DB_USERNAME |
— | Database user |
DB_PASSWORD |
— | Database password |
SESSION_DRIVER |
file |
Session driver |
SESSION_LIFETIME |
120 |
Session duration in minutes |
PHP runtime settings are also configurable via PHP_MEMORY_LIMIT, PHP_MAX_EXECUTION_TIME, PHP_DISPLAY_ERRORS, and related variables in .env.
Dependencies
| Package | Version | License |
|---|---|---|
illuminate/database |
^8.0 | MIT |
phpauth/phpauth |
^1.0 | MIT |
monolog/monolog |
^2.0 | MIT |
eftec/bladeone |
^4.0 | MIT |
eftec/bladeonehtml |
^2.5 | MIT |
twig/twig |
^3.20 | BSD-3-Clause |
symfony/console |
^5.0 | MIT |
symfony/mailer |
^7.2 | MIT |
symfony/cache |
^5.0 | MIT |
symfony/dotenv |
^6.4 | MIT |
symfony/event-dispatcher |
^5.0 | MIT |
symfony/filesystem |
^5.0 | MIT |
symfony/translation |
^5.0 | MIT |
symfony/mime |
^6.4 | MIT |
robmorgan/phinx |
^0.12.0 | MIT |
defuse/php-encryption |
^2.2 | MIT |
paragonie/random_compat |
^9.99 | MIT |
rakit/validation |
^1.4 | MIT |
nesbot/carbon |
^2.0 | MIT |
league/flysystem |
^1.1 | MIT |
intervention/image |
^2.5 | MIT |
predis/predis |
^1.1 | MIT |
php-di/php-di |
^7.0 | MIT |
pecee/simple-router |
^5.4 | MIT |
nyholm/psr7 |
^1.8 | MIT |
fakerphp/faker |
^1.24 | MIT |
delight-im/auth |
^8.3 | MIT |
delight-im/db |
^8.3 | MIT |
delight-im/cookie |
^8.3 | MIT |
delight-im/http |
^8.3 | MIT |
google/recaptcha |
^1.2 | BSD-3-Clause |
guzzlehttp/guzzle |
^7.0 | MIT |
guzzlehttp/promises |
^1.5 | MIT |
guzzlehttp/psr7 |
^2.0 | MIT |
License
This project is licensed under the MIT License. You may use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, provided the original license and copyright notice are included.
See LICENSE for the full license text.
© 2026 Marco Costa — All rights reserved under the MIT License.