globus-studio / atom
Atom - PHP 8.5 micro-framework. Single PCRE router, template engine, DI, validation, sessions, CLI.
Requires
- php: >=8.5
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.0
README
Atom ⚛
PHP 8.5 micro‑framework. Single PCRE router, template engine, DI, validation, sessions, database, CLI.
Why Atom
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.
Scope of Application
| 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 |
Install
composer require globus-studio/atom
Quick start
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();
Features
| 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`. |
Example
// .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();
Project structure
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
Running tests
composer test
composer test-coverage
composer stan
Docs & resources
- Full documentation — sidebar, all components, code examples
- Skill set — AI‑assistant knowledge: routing, HTTP, templates, validation, ORM, DI, CLI, middleware
- License — GPL-3.0-or-later
License
GPL-3.0-or-later. See LICENSE.