Grav
Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS
Atom - PHP 8.5 micro-framework. Single PCRE router, template engine, DI, validation, sessions, CLI.
PHP 8.5 micro‑framework. Single PCRE router, template engine, DI, validation, sessions, database, CLI.
Zero dependencies. Just PHP 8.5. No HTTP factory, no annotations - pure PHP with PCRE at its core.
Minimal codebase. Read the entire framework in 20 minutes. Current suite: 728 tests, 1108 assertions, 85.29% line coverage, clean PHPStan level 5.
One regex dispatches all routes. 10 000 routes = one preg_match via (?|...(*:N)) branch-reset + MARK. JIT-compiled, O(1) per request.
Batteries included. Validation on 18 attribute rules, Twig-like templates, sessions with CSRF rotation, CORS, file uploads, database, logger with rotation, CLI with help - things you'd otherwise compose from 5 packages.
Built for APIs and full-stack. JSON body parsing, Bearer token extraction, method spoofing, cache headers - everything you need for a REST API. Templates with inheritance, blocks, filters - everything you need for server-rendered pages.
Use it for: REST APIs, microservices, admin panels, static-site backends, MVPs, prototyping, educational projects, anything where you want full control without a framework fighting you.
| Scenario | Fit | Notes |
|---|---|---|
| REST API | Excellent | JSON body auto-parse, Bearer token, method spoofing, CORS, status codes |
| Microservice | Excellent | Zero deps, single-file deploy, 850 lines of code |
| Admin panel | Good | Templates with inheritance, CSRF, sessions, validation |
| Static-site backend | Good | Template engine, routing, config from .env |
| MVP / Prototype | Excellent | Full stack in one file, rapid iteration |
| Hobby project | Excellent | Easy to learn, zero config needed |
| High-traffic API | Good | O(1) routing, JIT-compiled PCRE, route cache |
| Real-time / WebSocket | Good | Built-in WebSocket server, rooms, broadcast |
| Enterprise CMS | Not suitable | No migrations, no admin generator |
| E-commerce | Possible | Would need custom cart/payment logic, DB only |
| SPA backend | Good | JSON API + CORS + JWT via Bearer token |
| Server-rendered pages | Good | Template inheritance, blocks, filters, auto-escape |
composer require globus-studio/atom
use Atom\{Application, Config}; $app = new Application(Config::fromEnv(__DIR__ . '/.env')); $app->router->get('/', 'HomeController@index'); $app->router->group('/api', ['Auth'], fn($r) => { $r->get('/users/{id}', 'UserController@show', 'user.show'); $r->post('/users', 'UserController@create'); }); $app->run();
| Component | Description |
|---|---|
| Router | Single preg_match dispatch via (?|...(*:N)). Groups, URL gen, attributes, signature-aware cache. |
| Templates | Twig-like → compiled PHP classes. Extends, blocks, filters, raw blocks. |
| Validation | 18 attribute rules: #[Required] #[Email] #[Regex] #[Min] #[Max] #[Integer] #[Between] #[In] #[Url] #[Nullable] #[Confirmed] #[Ip] #[Domain] #[Mac] #[FloatVal] #[Boolean] #[Uuid] #[Each] |
| Database | Minimal PDO wrapper: all(), one(), single(), run(), prepared statements. |
| Middleware | Closure |
| Session | get/set/flash/regenerate, CSRF token generation & rotation. |
| CLI | `bin/atom list/help/routes/cache/ws:serve`, custom commands with descriptions, `NO_COLOR` support. |
| Request | Property hooks, JSON body, Bearer token, _method spoofing, file uploads. |
| Response | html/json/text/redirect/noContent, cookies, cache headers, header injection shield. |
| Container | DI: bind, singleton, instance, has, recursive autowire. |
| Config | `fromEnv('.env')` with `APP_ENV` profiles (`.env.production`), `APP_DEBUG`, `APP_CACHE_DIR`, `APP_VIEWS_DIR`, `APP_TIMEZONE`, `APP_LOG_LEVEL`, `APP_LOG_MAX_SIZE`, `APP_NAME`, `APP_ROUTE_CACHE`, `APP_VIEW_CACHE`, `APP_CACHE_DRIVER`, `WS_HOST`, `WS_PORT`. |
| Logger | File-based, 7 levels, min-level filter, context, atomic writes, rotation, clear. |
| HTTP Test Client | HttpClient — fluent API: $client->get('/users')->assertOk()->assertJson(['id' => 1]). |
| Rate Limiter | #[RateLimit(max: 60, window: 60)] middleware — per-IP request limiting. |
| Health Check | $router->health('/health', fn() => ['db' => true]) — Kubernetes-ready. |
| Paginator | Paginator::from($req)->paginate($items, $total) — page/perPage/total/pages. |
| Encryption | `Encrypt::encrypt()` / `Encrypt::decrypt()` — AES-256-GCM with key derivation. |
| Cache | `$app->cache()`, PSR-16-like: `set/get/has/delete/flush`, TTL, `remember`, atomic counters, ArrayDriver, FileDriver. |
| ORM | Model, guarded Query builder, Relations (`hasMany`, `belongsTo`, `hasOne`), eager loading, Pagination. |
| WebSocket | `$app->ws()`, room management, broadcast, RFC 6455 handshake/frame validation, CLI `ws:serve`. |
// .env APP_DEBUG=true DB_DSN=sqlite:/var/app/db.sqlite APP_TIMEZONE=Europe/Moscow
// public/index.php use Atom\{Application, Config}; use Atom\Database\Database; use Atom\Http\Response; use Atom\Support\Logger; use Atom\Validation\{Required, Email}; $config = Config::fromEnv(__DIR__ . '/../.env'); $app = new Application($config); $app->container->singleton(Database::class, fn() => new Database($config->get('DB_DSN'))); $app->container->singleton(Logger::class, fn() => new Logger($config->get('APP_LOG_FILE'), $config->logLevel)); final class CreateUser { #[Required] public string $name = ''; #[Required] #[Email] public string $email = ''; } $app->router->post('/users', 'UserController@create'); $app->router->get('/users/{id}', 'UserController@show', 'user.show'); class UserController { public function __construct(private Database $db, private Logger $log) {} public function create(Request $req): Response { try { $dto = $req->validate(CreateUser::class); } catch (ValidationException $e) { return Response::json($e->errors, StatusCode::BAD_REQUEST); } $this->db->run('INSERT INTO users (name,email) VALUES (?,?)', [$dto->name, $dto->email]); $this->log->info('user created', ['name' => $dto->name]); return Response::json(['id' => $this->db->lastId()], StatusCode::CREATED); } public function show(string $id): Response { $user = $this->db->one('SELECT * FROM users WHERE id = ?', [$id]); return $user ? Response::json($user) : Response::json(['error' => 'Not found'], StatusCode::NOT_FOUND); } } $app->run();
src/Atom/
├── Config.php # debug, cacheDir, viewsDir, timezone, logFile, logLevel, logMaxSize, appName, fromEnv(), get()
├── Constants.php # framework constants
├── Application.php # entry point, boot, run
├── Console/Console.php # CLI: list, help, routes, cache, custom commands, NO_COLOR
├── Cache/
│ ├── Cache.php # PSR-16-like: set, get, has, delete, flush, remember
│ ├── Driver.php # driver interface
│ ├── ArrayDriver.php # in-memory TTL driver
│ └── FileDriver.php # file-based TTL driver
├── Container/Container.php # DI: bind, singleton, instance, has, autowire
├── Database/Database.php # PDO wrapper: all, one, single, run
├── Orm/
│ ├── Model.php # base model class
│ ├── Query.php # query builder
│ ├── Relation.php # base relation
│ ├── HasMany.php # hasMany relation
│ ├── BelongsTo.php # belongsTo relation
│ ├── HasOne.php # hasOne relation
│ ├── Column.php # column attribute
│ ├── PrimaryKey.php # primary key attribute
│ └── Table.php # table name attribute
├── Http/
│ ├── Request.php # hooks, JSON body, Bearer, _method, file(), validate()
│ ├── Response.php # html, json, text, redirect, cookies, cache, send()
│ ├── Session.php # get/set, flash, regenerate, csrfToken, validateCsrf
│ ├── StatusCode.php # enum 200..503
│ └── UploadedFile.php # typed $_FILES: ok, size, ext, root-bound move()
├── Middleware/
│ ├── MiddlewareInterface.php
│ ├── Cors.php # preflight + CORS headers, origin reflection
│ ├── Csrf.php # CSRF token validation with rotation
│ ├── Pipeline.php # onion: Closure | object | string
│ └── RateLimit.php # per-IP request rate limiting
├── Routing/
│ ├── Route.php # #[Route] attribute
│ ├── CompiledRoute.php # internal representation
│ ├── RouteCompiler.php # single PCRE regex
│ └── Router.php # dispatch, groups, url(), cache, routes(), health()
├── WebSocket/
│ ├── Server.php # RFC 6455 event loop, rooms, broadcast
│ └── Connection.php # connection wrapper, send, sendJson, ping, close
├── Support/
│ ├── Logger.php # file logger: 7 levels, rotate, clear, maxSize
│ ├── Regex.php # PCRE wrapper
│ ├── Paginator.php # page/perPage/total/pages from request
│ └── Encrypt.php # AES-256-GCM encryption
├── Test/
│ └── HttpClient.php # fluent API test client
├── Validation/
│ └── Validator.php # 18 attribute rules + ValidationException
└── View/
├── Compiler.php # Twig-like → PHP, nested braces, for-loop shadow restore
├── Engine.php # render, filters, globals
└── Template.php # base template class
composer test composer test-coverage composer stan
GPL-3.0-or-later. See LICENSE.
Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS
A library for validating emails against several RFCs
A JavaScript library for entering and validating international telephone numbers
Maps an HTTP request to a set of configuration variables
Nouvelle version disponible.