From Academic to Professional
From academic MVC to professional web architecture (part 1 of 2)
💡 Professional means: understandable, testable, extensible,
secure structure
Development of a modular mini-framework as a long-term project foundation
Goal:
This project serves as an architectural reference for developing
scalable web applications. It demonstrates the gradual transition from an
academic MVC structure to a professional, modular web architecture.
The end result is not a single project, but a lightweight
mini-framework that:
- serves as a stable foundation for any web project
- enables long-term extensibility
- avoids later complete refactors
"Build the right chassis once – then just swap modules."
Starting Point:
To demonstrate this concept practically, I work in two phases with existing demo projects:
Phase 1: As a starting point, I use my DemoMVC project – a typical academic MVC implementation that contains all essential concepts, but does not yet have a professional structure.
Phase 2: In the second phase, I use the Demologin project, built on the same DemoMVC basis, but it already has a complete login functionality implemented.
Stages:
| STAGE | FOCUS | GOAL | PHASE |
|---|---|---|---|
| 1 | Academic MVC | Understanding | 1 |
| 2 | Folder Structure | Security & Overview | 1 |
| 3 | Bootstrap & Router | Index Relief & Request Flow | 1 |
| 4 | .htaccess Configuration | Access Security (Foundation) | 1 |
| (5) | Services & Classes | Structure & Testability (later) | 2 |
| (6) | Mini-Framework | Long-term Scalability (later) | 2 |
👉 Each stage works independently 👉 No "Start from scratch" moments
Structure:
Goal: Security & Overview, without refactor
Principle: Only public/ is publicly accessible – everything else protected.
Project/
├─ app/
│ ├─ config/
│ ├─ control/
│ ├─ helper/
│ ├─ model/
│ ├─ Router/
│ ├─ service/
│ ├─ view/
│ └─ bootstrap.php
│ └─ router.php
│ └─ session.php
├─ doc/...
├─ public/ ← only public
│ ├─ css/
│ └─ img/
│ ├─ js/
│ ├─ index.php ← Single Entry Point
├─ sql/
├─ storage/
│ ├─ logs/
│ └─ upload/
└─ README.mdIndex Relief:
Problem:
In academic MVC, index.php does too much:
- Router
- Controller
- Security Gate
- Workflow Orchestrator
👉 Single Point of Chaos
Goal:
index.php becomes:
- Small
- Starting point
- no logic
Solution:
- Externalize router
- Centralized bootstrap logic
- Preparation for autoloading
- Clear request pipeline
Request Pipeline
Request ↓ public/index.php ↓ Bootstrap ↓ Router ↓ Controller ↓ Service ↓ View / Response
Bootstrap:
Initializes:
- Config
- Session
- Helper
- Controller & Service
- Model & View
Router:
Tasks:
- URL → Controller / Action
- Extract parameters
- Handle errors cleanly
Implementation:
- Create: app/bootstrap.php
- Move import paths from index to the new bootstrap
- Move switch($page) into Controller embedded in a function
- Move Controller contents into Service folder and distribute across new files:
App/services/
│ ├─ AuthService.php
│ ├─ UserService.php
│ ├─ ProfileService.php
│ ├─ SessionService.php
│ └─ UploadService.php- Create: app/Router/Router.php
- Move language and page checks from session.php to router.php
Secure Access with .htaccess (Two-File Architecture)
Goal: Multi-layered protection with clear task separation
Principle: Two .htaccess files work together for maximum security
Base .htaccess (Root):
# BASE/.HTACCESS (Root directory)
# Task separation: URL redirection & Basic protection
# PROTECTION OF .HTACCESS FILE
RewriteRule ^\.htaccess$ - [F]
<IfModule mod_rewrite.c>
RewriteEngine On
# REWRITE ALL REQUESTS TO PUBLIC/
RewriteCond %{REQUEST_URI} !/public/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ public/$1 [QSA,L]
# DELIVER STATIC FILES DIRECTLY
RewriteCond %{REQUEST_URI} !/public/
RewriteCond %{REQUEST_FILENAME} !-f
# EVERYTHING ELSE TO PUBLIC/INDEX.PHP
RewriteRule ^(.*)$ public/index.php [QSA,L]
</IfModule>Public .htaccess (Application):
# BASE/PUBLIC/.HTACCESS
# Task separation: Application routing
RewriteRule ^\.htaccess$ - [F]
<IfModule mod_rewrite.c>
RewriteEngine On
# DELIVER EXISTING FILES/DIRECTORIES DIRECTLY
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# EVERYTHING ELSE → INDEX.PHP (FRONT CONTROLLER)
RewriteRule ^ index.php [L]
</IfModule>Why two files:
- Multi-layered security: Double protection against directory traversal
- Task separation: Root manages access, Public manages routing
- Debugging: Easier to test and maintain
- Flexibility: Can be adapted per environment
How they work together:
- Step 1: Root .htaccess redirects all requests to public/
- Step 2: Public .htaccess checks if file/directory exists
- Step 3: Static files are delivered directly
- Step 4: Everything else goes to index.php (Front Controller)
👉 Together with the folder structure, this forms the security foundation of the entire project. No sensitive files are ever publicly accessible.