Raptor Framework
Clean architecture object-oriented web development framework
A multi-layered, multi-tenant, full-featured CMS PHP web framework built on PSR standards with RBAC access control. It ships with two apps by default - Web (public website) and Dashboard (admin panel) - and brings the other codesaur ecosystem packages together into one working system.
- PSR-7/PSR-15 middleware-based architecture
- JWT + Session authentication
- Multi-tenant organizations with RBAC
- Multi-language support (Localization) - one URL prefix per language (/en/...), canonical + hreflang emitted automatically
- Language-neutral records (code = "*") shown in every language - news, pages and products
- CMS modules: News, Pages, Files, References, Settings
- Shop module: Products, cart, multi-product orders, stock tracking (subtracted on confirmation, restored on cancel), Reviews
- MySQL or PostgreSQL supported
- SQL file-based database migration system
- codesaur/template engine (Twig-style syntax, XSS protection through autoescape)
- OpenAI integration (moedit editor)
- PSR-3 logging, PSR-14 Event Dispatcher
- Email (Brevo API, SMTP, PHP mail), Discord webhook notifications
- SEO: Search, Sitemap, XML Sitemap, RSS feed
- Spam protection (honeypot, HMAC token, rate limiting, Cloudflare Turnstile)
- CSRF protection
- Runs in any environment: VPS, dedicated, cloud or shared hosting - method override and body encoding keep it working even behind a mod_security / LiteSpeed WAF
- File-based cache (PSR-16), Trash recovery, sidebar badge system
Architecture
One entry point, as many apps as you need - two by default. A request travels through the middleware chain to the router, controller and template.
public_html/index.php (Entry point) | |-- /dashboard/* -> Dashboard\Application (Admin Panel) | |-- Middleware: ErrorHandler -> MethodOverride -> BodyEncoding | | -> Session -> JWT -> Container -> Localization -> Settings | |-- Routers: Login, Users, Organization, RBAC, Localization, Contents, | | Messages, Comments, Logs, Template, Shop, Development, Migration | \-- Controllers -> Templates -> HTML Response | \-- /* -> Web\Application (Public Website) |-- Middleware: ExceptionHandler -> MethodOverride -> BodyEncoding | -> Container -> Session -> Localization -> Settings |-- Routers: WebRouter, PortalRouter \-- Controllers -> Templates -> HTML Response Request flow: Browser -> index.php -> .env -> ServerRequest -> Application selection (by URL path) -> Middleware chain (in order) -> Router match -> Controller::action() -> Model (DB) -> FileTemplate (codesaur/template) -> render() -> HTML Response -> Browser1:1
Middleware pipeline
PSR-15
- ErrorHandler
- MethodOverrideMiddleware
- BodyEncodingMiddleware
- SessionMiddleware
- JWTAuthMiddleware
- ContainerMiddleware
- LocalizationMiddleware
- SettingsMiddleware
- CsrfMiddleware (per-route)
- ExceptionHandler
- MethodOverrideMiddleware
- BodyEncodingMiddleware
- ContainerMiddleware
- SessionMiddleware
- LocalizationMiddleware
- SettingsMiddleware
Dashboard modules
The admin panel uses a package-by-feature layout: each module bundles its Controller, Model and templates in one folder.
Authentication
JWT + Session, password reset, signup requests, login attempt limits
Users & Organizations
Multi-tenant organizations, org switcher, soft delete
RBAC
Roles, permissions grouped by alias; coder / admin / manager / editor / viewer
Localization
Languages and translation texts with caching
Content
News, pages (tree), reference tables, settings, files, comments
Shop
Products, web cart, multi-product orders, delivery address, stock tracking, reviews (1-5 stars)
Messages
Contact form messages with email replies
Logs & Protocol
PSR-3 log tables, per-record history, sidebar badges
Trash
Restore deleted records with their original IDs
Migration
SQL file-based, forward-only, with a security scanner
Mail & Notifications
Brevo API / SMTP / PHP mail, Discord webhook, PSR-14 events
Development
Dev requests, manuals, AI helper (moedit)
Quick start
Create an empty database and run one command - all tables and seed data are created automatically on first run.
- PHP 8.2.1+
- Composer
- MySQL / PostgreSQL
- ext-gd
- ext-intl
composer create-project codesaur/raptor my-project
# Environment (development / production)
CODESAUR_APP_ENV=development
# Database (mysql | pgsql)
RAPTOR_DB_DRIVER=mysql
RAPTOR_DB_HOST=localhost
RAPTOR_DB_NAME=raptor
RAPTOR_DB_USERNAME=root
RAPTOR_DB_PASSWORD=
# JWT (secret is auto-generated)
RAPTOR_JWT_ALGORITHM=HS256
RAPTOR_JWT_LIFETIME=2592000
# WAF compatibility (mod_security)
RAPTOR_WAF_BODY_ENCODING=true
The document root MUST be public_html/ - .env, application/ and vendor/ live above it and stay unreachable by URL.
Ships with a PHPUnit 11 suite of unit and integration tests. Integration tests use the .env.testing config on a separate test database; each test runs inside a transaction and rolls back on teardown.
composer test # All tests
composer test:unit # Unit tests only
composer test:integration # Integration tests only
Directory structure
package-by-feature
raptor/ |-- application/ # PHP application code (package-by-feature) | |-- dashboard/ # Admin panel + shared platform modules | \-- web/ # Public website application |-- public_html/ # Document root (index.php, assets/) |-- database/ | \-- migrations/ # SQL migration files |-- tests/ # PHPUnit tests (unit, integration) |-- docs/ # Documentation (en/, mn/, conf.example/) |-- .github/ | \-- workflows/ # CI + auto deploy |-- logs/ # Error logs |-- cache/ # Framework file cache (PSR-16) |-- protected/ # Protected files (outside docroot) |-- composer.json |-- phpunit.xml \-- LICENSE # MIT1:1
Core classes
application/dashboard/ + application/web/
| Class | Purpose |
|---|---|
Dashboard\Application | Admin panel middleware + router registration |
Web\Application | Public website middleware + router registration |
Dashboard\DatabaseConnection | Opens the PDO connection - MySQL / PostgreSQL chosen in .env |
Dashboard\Controller | Base for all controllers: PDO, RBAC, template, log |
Dashboard\MethodOverrideMiddleware | Restores PUT/PATCH/DELETE from X-HTTP-Method-Override (WAF) |
Dashboard\BodyEncodingMiddleware | Decodes base64-encoded POST bodies (WAF) |
Dashboard\ContainerMiddleware | Injects the PSR-11 container and its services into the request |
Dashboard\SessionMiddleware | Opens the session and closes it early when no write is needed |
Dashboard\Authentication\JWTAuthMiddleware | Validates the JWT and builds the User object |
Dashboard\Localization\LocalizationMiddleware | Determines language and translations |
Dashboard\Content\SettingsMiddleware | Injects the system settings into the request |
Dashboard\CsrfMiddleware | Per-route CSRF protection |
Dashboard\Authentication\User | The signed-in user: can(), is(), organization scope |
Dashboard\RBAC\RBAC | A user roles and permissions set (cached) |
Dashboard\Template\DashboardTrait | dashboard.html layout, sidebar and organization switcher |
Web\Template\TemplateController | Web index.html layout, SEO meta and navigation |
Web\Shop\Cart | Session cart - stores only [product_id => quantity], prices and stock are re-read from the DB |
Dashboard\CacheService | PSR-16 file-based cache |
Dashboard\Log\Logger | PSR-3 logging into the {table}_log tables |
Dashboard\Mail\Mailer | Mailer (Brevo API, SMTP, PHP mail) |
Dashboard\Notification\EventDispatcher | PSR-14 event dispatcher |
Dashboard\Notification\DiscordNotifier | Discord webhook notifications |
Dashboard\Migration\MigrationRunner | Runs SQL migration files with a driver-aware statement splitter |
Dashboard\Migration\MigrationSecurityScanner | Flags writes to sensitive tables and DCL statements |
Dashboard\Trash\TrashModel | Stores deleted records and restores them |
Dashboard\File\FileController | Base logic for file uploads and deletion |
Dashboard\Badge\BadgeController | Counts unseen activity for the sidebar badges |
Dashboard\Exception\ErrorHandler | Template-based error pages |
Ecosystem packages
Every package is standalone and installable into any PHP project via Composer. Raptor combines them into a complete framework.
| Package | Installed version | PSR | Purpose |
|---|---|---|---|
| codesaur/http-message | v3.0.4 | PSR-7 | Clean, minimal, object-oriented HTTP Message component (PSR-7) |
| codesaur/router | v6.0.1 | - | Lightweight, fast, object-oriented routing component |
| codesaur/http-application | v7.0.1 | PSR-7, PSR-15 | Lightweight, flexible HTTP Application core compliant with PSR-7 & PSR-15 |
| codesaur/dataobject | v10.2.1 | - | PDO-based data model and table management component (MySQL / PostgreSQL / SQLite) |
| codesaur/template | v5.0.1 | - | Self-contained PHP template engine - autoescape, filters, functions, macros, expression parser |
| codesaur/http-client | v2.1.2 | - | Lightweight client component for sending HTTP requests and building/sending MIME email |
| codesaur/container | v3.2.0 | PSR-11 | Lightweight, fast, PSR-11 compliant dependency injection container |
Why "Raptor"?
The name honors the remarkable Velociraptor, a dinosaur whose fossils were first unearthed in Mongolia's Gobi Desert (1923). Its author, Narankhuu, is a keen reader on dinosaurs and natural history. codesaur is his own playful name - code + saur - a nod to writing C since 1997: an old-school "coding dinosaur".
Author: Narankhuu (codesaur)Thanks to Gerege Systems LLC and its founder Erdenebat Ts for their financial support and valuable input during the development of this framework.
gerege.com