<?
php
/**
* super_long_app.php
*
* A long, self-contained PHP script demonstrating multiple components in one file:
* - Utils and logging
* - Simple validators
* - In-memory DB (with optional SQLite persistence)
* - Models (User, Post, Comment)
* - Services (AuthService, ContentService)
* - Simple Router for JSON REST API
* - CLI commands (seed, list, export, server)
* - Simple templating
* - Export / Import JSON
* - Minimal test runner
*
* Usage examples:
* php super_long_app.php help
* php -S [Link]:8000 super_long_app.php # run built-in web server entry
*
* Note: To run as web server, use: php -S [Link]:8000 super_long_app.php
*/
// -------------------------
// Autoload-like helpers
// -------------------------
if (!defined('APP_START')) define('APP_START', microtime(true));
date_default_timezone_set('Asia/Ho_Chi_Minh');
// -------------------------
// Utilities
// -------------------------
class Utils {
public static function uuid(): string {
// simple UUID v4-ish
$data = random_bytes(16);
$data[6] = chr((ord($data[6]) & 0x0f) | 0x40);
$data[8] = chr((ord($data[8]) & 0x3f) | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
public static function nowIso(): string {
return gmdate('Y-m-d\TH:i:s\Z');
}
public static function prettyJson($data): string {
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
public static function readStdin(): string {
$content = '';
while (!feof(STDIN)) {
$content .= fgets(STDIN);
}
return $content;
}
public static function ensureDir(string $path) {
$dir = dirname($path);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
}
public static function slugify(string $text): string {
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
$text = preg_replace('~[^-\w]+~', '', $text);
$text = trim($text, '-');
$text = preg_replace('~-+~', '-', $text);
$text = strtolower($text);
if (empty($text)) {
return substr(md5(uniqid('', true)), 0, 8);
}
return $text;
}
}
// -------------------------
// Simple Logger
// -------------------------
class Logger {
public static function info(string $msg) {
echo "[" . date('Y-m-d H:i:s') . "] INFO: " . $msg . PHP_EOL;
}
public static function error(string $msg) {
echo "[" . date('Y-m-d H:i:s') . "] ERROR: " . $msg . PHP_EOL;
}
}
// -------------------------
// Validators
// -------------------------
class Validators {
public static function email(string $email): bool {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
public static function nonEmpty($v): bool {
return !is_null($v) && trim((string)$v) !== '';
}
public static function lengthBetween(string $s, int $min, int $max): bool {
$len = mb_strlen($s);
return $len >= $min && $len <= $max;
}
}
// -------------------------
// In-Memory DB with optional SQLite persistence
// -------------------------
class InMemoryDB {
private array $store = [];
private ?\PDO $pdo = null;
private bool $useSqlite = false;
private string $sqlitePath = '';
public function __construct(bool $useSqlite = false, string $sqlitePath = 'data/[Link]') {
$this->useSqlite = $useSqlite;
$this->sqlitePath = $sqlitePath;
if ($useSqlite) {
$this->initSqlite($sqlitePath);
}
}
private function initSqlite(string $path) {
Utils::ensureDir($path);
$dsn = 'sqlite:' . $path;
$this->pdo = new PDO($dsn);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// create simple tables if not exist
$this->pdo->exec("CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY,
email TEXT UNIQUE, name TEXT, password_hash TEXT, role TEXT, bio TEXT, created_at
TEXT, updated_at TEXT)");
$this->pdo->exec("CREATE TABLE IF NOT EXISTS posts (id TEXT PRIMARY KEY,
author_id TEXT, title TEXT, content TEXT, tags TEXT, published INTEGER, slug TEXT,
created_at TEXT, updated_at TEXT)");
$this->pdo->exec("CREATE TABLE IF NOT EXISTS comments (id TEXT PRIMARY
KEY, post_id TEXT, author_id TEXT, content TEXT, created_at TEXT, updated_at TEXT)");
}
// Generic store functions (in-memory)
public function insert(string $type, array $record): array {
$id = $record['id'] ?? Utils::uuid();
$now = Utils::nowIso();
$record['id'] = $id;
$record['created_at'] = $record['created_at'] ?? $now;
$record['updated_at'] = $now;
$this->store[$type][$id] = $record;
if ($this->useSqlite) {
$this->saveToSqlite($type, $record);
}
return $record;
}
public function update(string $type, string $id, array $attrs): ?array {
if (!isset($this->store[$type][$id])) return null;
$this->store[$type][$id] = array_merge($this->store[$type][$id], $attrs);
$this->store[$type][$id]['updated_at'] = Utils::nowIso();
if ($this->useSqlite) {
$this->saveToSqlite($type, $this->store[$type][$id]);
}
return $this->store[$type][$id];
}
public function delete(string $type, string $id): bool {
if (!isset($this->store[$type][$id])) return false;
unset($this->store[$type][$id]);
if ($this->useSqlite) {
$stmt = $this->pdo->prepare("DELETE FROM $type WHERE id = :id");
$stmt->execute([':id' => $id]);
}
return true;
}
public function find(string $type, string $id): ?array {
if ($this->useSqlite && empty($this->store[$type])) {
$this->loadFromSqlite($type);
}
return $this->store[$type][$id] ?? null;
}
public function where(string $type, callable $predicate): array {
if ($this->useSqlite && empty($this->store[$type])) {
$this->loadFromSqlite($type);
}
$result = [];
foreach ($this->store[$type] ?? [] as $rec) {
if ($predicate($rec)) $result[] = $rec;
}
return $result;
}
public function all(string $type): array {
if ($this->useSqlite && empty($this->store[$type])) {
$this->loadFromSqlite($type);
}
return array_values($this->store[$type] ?? []);
}
public function toArray(): array {
return $this->store;
}
public function exportJson(string $path): string {
Utils::ensureDir($path);
$data = $this->toArray();
file_put_contents($path, Utils::prettyJson($data));
return $path;
}
public function importJson(string $path) {
if (!file_exists($path)) throw new Exception("Import file not found: $path");
$json = file_get_contents($path);
$data = json_decode($json, true);
if (!is_array($data)) throw new Exception("Invalid JSON import file");
$this->store = $data;
if ($this->useSqlite) {
// naive sync: clear sqlite and reinsert
$this->pdo->exec("DELETE FROM users");
$this->pdo->exec("DELETE FROM posts");
$this->pdo->exec("DELETE FROM comments");
foreach ($this->store as $type => $entries) {
foreach ($entries as $id => $rec) {
$this->saveToSqlite($type, $rec);
}
}
}
}
// SQLite helpers
private function saveToSqlite(string $type, array $rec) {
if (!$this->pdo) return;
if ($type === 'users') {
$stmt = $this->pdo->prepare("REPLACE INTO users
(id,email,name,password_hash,role,bio,created_at,updated_at) VALUES
(:id,:email,:name,:password_hash,:role,:bio,:created_at,:updated_at)");
$stmt->execute([
':id' => $rec['id'],
':email' => $rec['email'] ?? null,
':name' => $rec['name'] ?? null,
':password_hash' => $rec['password_hash'] ?? null,
':role' => $rec['role'] ?? null,
':bio' => $rec['bio'] ?? null,
':created_at' => $rec['created_at'] ?? null,
':updated_at' => $rec['updated_at'] ?? null
]);
} elseif ($type === 'posts') {
$stmt = $this->pdo->prepare("REPLACE INTO posts
(id,author_id,title,content,tags,published,slug,created_at,updated_at) VALUES
(:id,:author_id,:title,:content,:tags,:published,:slug,:created_at,:updated_at)");
$stmt->execute([
':id' => $rec['id'],
':author_id' => $rec['author_id'] ?? null,
':title' => $rec['title'] ?? null,
':content' => $rec['content'] ?? null,
':tags' => isset($rec['tags']) ? json_encode($rec['tags'],
JSON_UNESCAPED_UNICODE) : null,
':published' => !empty($rec['published']) ? 1 : 0,
':slug' => $rec['slug'] ?? null,
':created_at' => $rec['created_at'] ?? null,
':updated_at' => $rec['updated_at'] ?? null
]);
} elseif ($type === 'comments') {
$stmt = $this->pdo->prepare("REPLACE INTO comments
(id,post_id,author_id,content,created_at,updated_at) VALUES
(:id,:post_id,:author_id,:content,:created_at,:updated_at)");
$stmt->execute([
':id' => $rec['id'],
':post_id' => $rec['post_id'] ?? null,
':author_id' => $rec['author_id'] ?? null,
':content' => $rec['content'] ?? null,
':created_at' => $rec['created_at'] ?? null,
':updated_at' => $rec['updated_at'] ?? null
]);
}
}
private function loadFromSqlite(string $type) {
if (!$this->pdo) return;
$rows = $this->pdo->query("SELECT * FROM
$type")->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $r) {
if ($type === 'posts' && isset($r['tags'])) {
$r['tags'] = json_decode($r['tags'], true) ?: [];
}
$this->store[$type][$r['id']] = $r;
}
}
}
// -------------------------
// Models (simple array-based factories)
// -------------------------
class Models {
public static function user(array $attrs = []): array {
return array_merge([
'id' => $attrs['id'] ?? Utils::uuid(),
'email' => $attrs['email'] ?? null,
'name' => $attrs['name'] ?? ('User ' . rand(1000, 9999)),
'password_hash' => $attrs['password_hash'] ?? null,
'role' => $attrs['role'] ?? 'user',
'bio' => $attrs['bio'] ?? '',
'created_at' => $attrs['created_at'] ?? Utils::nowIso(),
'updated_at' => $attrs['updated_at'] ?? Utils::nowIso()
], $attrs);
}
public static function post(array $attrs = []): array {
$title = $attrs['title'] ?? ('Untitled ' . rand(1000, 9999));
return array_merge([
'id' => $attrs['id'] ?? Utils::uuid(),
'author_id' => $attrs['author_id'] ?? null,
'title' => $title,
'content' => $attrs['content'] ?? '',
'tags' => $attrs['tags'] ?? [],
'published' => $attrs['published'] ?? false,
'slug' => $attrs['slug'] ?? Utils::slugify($title),
'created_at' => $attrs['created_at'] ?? Utils::nowIso(),
'updated_at' => $attrs['updated_at'] ?? Utils::nowIso()
], $attrs);
}
public static function comment(array $attrs = []): array {
return array_merge([
'id' => $attrs['id'] ?? Utils::uuid(),
'post_id' => $attrs['post_id'] ?? null,
'author_id' => $attrs['author_id'] ?? null,
'content' => $attrs['content'] ?? '',
'created_at' => $attrs['created_at'] ?? Utils::nowIso(),
'updated_at' => $attrs['updated_at'] ?? Utils::nowIso()
], $attrs);
}
}
// -------------------------
// Services: AuthService (simple) and ContentService
// -------------------------
class AuthService {
private InMemoryDB $db;
public function __construct(InMemoryDB $db) {
$this->db = $db;
}
private function hashPassword(string $password): string {
$salt = bin2hex(random_bytes(8));
$hash = hash('sha256', $salt . $password);
return "sha256\${$salt}\${$hash}";
}
private function verifyPassword(string $password, string $stored): bool {
$parts = explode('$', $stored);
if (count($parts) !== 3 || $parts[0] !== 'sha256') return false;
list(, $salt, $digest) = $parts;
return hash('sha256', $salt . $password) === $digest;
}
public function register(string $email, string $password, ?string $name = null): array {
if (!Validators::email($email)) throw new Exception("Invalid email");
if (!Validators::lengthBetween($password, 6, 128)) throw new Exception("Password
must be >=6 chars");
$existing = $this->db->where('users', function($u) use ($email) {
return strtolower($u['email']) === strtolower($email);
});
if (!empty($existing)) throw new Exception("Email already registered");
$pw = $this->hashPassword($password);
$user = Models::user(['email' => strtolower($email), 'name' => $name, 'password_hash'
=> $pw]);
return $this->db->insert('users', $user);
}
public function authenticate(string $email, string $password): ?array {
$users = $this->db->where('users', function($u) use ($email) {
return strtolower($u['email']) === strtolower($email);
});
if (empty($users)) return null;
$user = $users[0];
if ($this->verifyPassword($password, $user['password_hash'])) return $user;
return null;
}
}
class ContentService {
private InMemoryDB $db;
public function __construct(InMemoryDB $db) {
$this->db = $db;
}
public function createPost(string $authorId, string $title, string $content, array $tags = []):
array {
$author = $this->db->find('users', $authorId);
if (!$author) throw new Exception("Author not found");
$post = Models::post(['author_id' => $authorId, 'title' => $title, 'content' => $content,
'tags' => $tags]);
return $this->db->insert('posts', $post);
}
public function publishPost(string $postId): ?array {
$p = $this->db->find('posts', $postId);
if (!$p) return null;
return $this->db->update('posts', $postId, ['published' => true]);
}
public function listPosts(bool $published = true): array {
return $this->db->where('posts', function($p) use ($published) {
return ($published ? !empty($p['published']) : true);
});
}
public function findBySlug(string $slug): ?array {
$found = $this->db->where('posts', function($p) use ($slug) { return ($p['slug'] ?? '') ===
$slug; });
return $found[0] ?? null;
}
public function addComment(string $postId, string $authorId, string $content): array {
$post = $this->db->find('posts', $postId);
$author = $this->db->find('users', $authorId);
if (!$post) throw new Exception("Post not found");
if (!$author) throw new Exception("Author not found");
$comment = Models::comment(['post_id' => $postId, 'author_id' => $authorId, 'content'
=> $content]);
return $this->db->insert('comments', $comment);
}
public function commentsForPost(string $postId): array {
return $this->db->where('comments', function($c) use ($postId) {
return ($c['post_id'] ?? '') === $postId;
});
}
public function postsByTag(string $tag): array {
return $this->db->where('posts', function($p) use ($tag) {
$tags = $p['tags'] ?? [];
return in_array(strtolower($tag), array_map('strtolower', $tags));
});
}
}
// -------------------------
// Sample Data Generator
// -------------------------
class SampleGenerator {
private InMemoryDB $db;
private ContentService $cs;
private AuthService $auth;
private array $names = ['Alice','Bob','Carol','Dave','Eve','Frank','Grace','Heidi','Ivan','Judy'];
private array $topics = [
'PHP tips and tricks','Understanding memory','Concurrency patterns',
'How to write clean code','Design patterns explained','Testing strategies',
'Performance tuning','DevOps basics','Web architecture','Refactoring legacy code'
];
public function __construct(InMemoryDB $db, AuthService $auth, ContentService $cs) {
$this->db = $db;
$this->auth = $auth;
$this->cs = $cs;
}
public function seed(int $users = 10, int $postsPerUser = 5, int $commentsPerPost = 3) {
$createdUsers = [];
for ($i = 0; $i < $users; $i++) {
$email = strtolower(substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 7)) .
'@[Link]';
$name = $this->names[array_rand($this->names)] . ' ' . chr(65 + rand(0,25));
$pwd = 'pass' . rand(1000,9999);
try {
$u = $this->auth->register($email, $pwd, $name);
$createdUsers[] = $u;
} catch (Exception $e) {
// collision or error - skip
}
}
$allUsers = $this->db->all('users');
if (empty($allUsers)) return;
foreach ($allUsers as $user) {
for ($p = 0; $p < $postsPerUser; $p++) {
$title = $this->topics[array_rand($this->topics)] . ' ' . rand(1,100);
$content = $this->lorem(rand(30, 100));
$tags =
array_slice(['php','devops','testing','patterns','design','performance','architecture'], 0,
rand(1,3));
try {
$post = $this->cs->createPost($user['id'], $title, $content, $tags);
if (rand(0,1)) {
$this->db->update('posts', $post['id'], ['published' => true]);
}
} catch (Exception $e) {
// skip
}
}
}
$posts = $this->db->all('posts');
foreach ($posts as $post) {
for ($c = 0; $c < $commentsPerPost; $c++) {
$author = $allUsers[array_rand($allUsers)];
$text = $this->lorem(rand(5, 30));
try {
$this->cs->addComment($post['id'], $author['id'], $text);
} catch (Exception $e) {
// skip
}
}
}
}
private function lorem(int $words = 20): string {
$pool = explode(' ', 'lorem ipsum dolor sit amet consectetur adipiscing elit sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua');
$out = [];
for ($i = 0; $i < $words; $i++) {
$out[] = $pool[array_rand($pool)];
}
return ucfirst(implode(' ', $out)) . '.';
}
}
// -------------------------
// Simple Templating (very basic)
// -------------------------
class View {
public static function render(string $template, array $params = []): string {
// $template: a simple string containing {{key}} placeholders
$output = $template;
foreach ($params as $k => $v) {
$output = str_replace('{{' . $k . '}}', htmlspecialchars((string)$v, ENT_QUOTES |
ENT_SUBSTITUTE, 'UTF-8'), $output);
}
return $output;
}
}
// -------------------------
// Minimal Router for JSON API
// -------------------------
class Request {
public string $method;
public string $path;
public array $query;
public $body;
public array $headers;
public function __construct() {
$this->method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$this->path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
$this->query = $_GET;
$this->headers = getallheaders ? getallheaders() : [];
$raw = file_get_contents('php://input');
$this->body = json_decode($raw, true) ?? $raw;
}
}
class Response {
public static function json($data, int $status = 200) {
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo Utils::prettyJson($data);
}
}
// -------------------------
// HTTP Handlers
// -------------------------
class Api {
private InMemoryDB $db;
private AuthService $auth;
private ContentService $cs;
public function __construct(InMemoryDB $db) {
$this->db = $db;
$this->auth = new AuthService($db);
$this->cs = new ContentService($db);
}
public function handle(Request $req) {
// routes:
// GET /api/users
if ($req->method === 'GET' && $req->path === '/api/users') {
$users = $this->db->all('users');
return Response::json($users);
}
// POST /api/users
if ($req->method === 'POST' && $req->path === '/api/users') {
$payload = is_array($req->body) ? $req->body : [];
try {
$user = $this->auth->register($payload['email'] ?? '', $payload['password'] ?? '',
$payload['name'] ?? null);
return Response::json($user, 201);
} catch (Exception $e) {
return Response::json(['error' => $e->getMessage()], 400);
}
}
// GET /api/posts
if ($req->method === 'GET' && $req->path === '/api/posts') {
$published = !isset($req->query['published']) || $req->query['published'] !== 'false';
$posts = $this->cs->listPosts($published);
return Response::json($posts);
}
// POST /api/posts
if ($req->method === 'POST' && $req->path === '/api/posts') {
$payload = is_array($req->body) ? $req->body : [];
try {
$post = $this->cs->createPost($payload['author_id'] ?? '', $payload['title'] ?? '',
$payload['content'] ?? '', $payload['tags'] ?? []);
return Response::json($post, 201);
} catch (Exception $e) {
return Response::json(['error' => $e->getMessage()], 400);
}
}
// POST /api/posts/{post_id}/comments
if (preg_match('#^/api/posts/([^/]+)/comments$#', $req->path, $m) && $req->method
=== 'POST') {
$postId = $m[1];
$payload = is_array($req->body) ? $req->body : [];
try {
$c = $this->cs->addComment($postId, $payload['author_id'] ?? '',
$payload['content'] ?? '');
return Response::json($c, 201);
} catch (Exception $e) {
return Response::json(['error' => $e->getMessage()], 400);
}
}
// GET /api/export
if ($req->method === 'GET' && $req->path === '/api/export') {
$path = 'exports/db_' . time() . '.json';
$this->db->exportJson($path);
return Response::json(['exported_to' => $path]);
}
// fallback
return Response::json(['error' => 'not found'], 404);
}
}
// -------------------------
// CLI Entrypoint and Commands
// -------------------------
class CLI {
public static function run(array $argv) {
$script = array_shift($argv);
$cmd = $argv[0] ?? null;
// default DB: in-memory without sqlite
$useSqlite = in_array('--sqlite', $argv, true);
$db = new InMemoryDB($useSqlite, 'data/[Link]');
$auth = new AuthService($db);
$cs = new ContentService($db);
$api = new Api($db);
$sg = new SampleGenerator($db, $auth, $cs);
switch ($cmd) {
case 'help':
case null:
echo "Usage: php super_long_app.php <command>\n";
echo "Commands:\n";
echo " help Show this help\n";
echo " seed [u p c] Seed sample data (users posts comments)\n";
echo " list users|posts|comments List records\n";
echo " export [file] Export DB to file\n";
echo " import <file> Import DB from file\n";
echo " server [host:port] Run built-in PHP server (see docs)\n";
echo " runserver Run script as router for built-in server (used by php -S
host:port super_long_app.php)\n";
echo " create_user <email> <password> [name]\n";
echo " test Run simple tests\n";
break;
case 'seed':
$u = isset($argv[1]) ? (int)$argv[1] : 10;
$p = isset($argv[2]) ? (int)$argv[2] : 5;
$c = isset($argv[3]) ? (int)$argv[3] : 3;
$sg->seed($u, $p, $c);
Logger::info("Seeded: users={$u}, postsPerUser={$p}, commentsPerPost={$c}");
break;
case 'list':
$type = $argv[1] ?? 'users';
if (!in_array($type, ['users','posts','comments'])) {
Logger::error("Unknown list type");
exit(1);
}
$recs = $db->all($type);
echo Utils::prettyJson($recs) . PHP_EOL;
break;
case 'export':
$file = $argv[1] ?? 'exports/db_' . time() . '.json';
$db->exportJson($file);
Logger::info("Exported to {$file}");
break;
case 'import':
$file = $argv[1] ?? null;
if (!$file) { Logger::error("Import file required"); exit(1); }
$db->importJson($file);
Logger::info("Imported from {$file}");
break;
case 'create_user':
$email = $argv[1] ?? null;
$pw = $argv[2] ?? null;
$name = $argv[3] ?? null;
if (!$email || !$pw) { Logger::error("email and password required"); exit(1); }
try {
$u = $auth->register($email, $pw, $name);
echo Utils::prettyJson($u) . PHP_EOL;
} catch (Exception $e) {
Logger::error($e->getMessage());
exit(1);
}
break;
case 'server':
// Note: In PHP, to use built-in server run: php -S [Link]:8000
super_long_app.php
echo "To run the built-in PHP web server, use:\n";
echo " php -S [Link]:8000 super_long_app.php\n";
echo "Then open [Link]
break;
case 'runserver':
// This branch is executed when script is used as router with php -S host:port script
$req = new Request();
$api->handle($req);
break;
case 'test':
self::runTests($db, $auth, $cs);
break;
default:
Logger::error("Unknown command: {$cmd}");
break;
}
}
private static function runTests(InMemoryDB $db, AuthService $auth, ContentService $cs)
{
$failures = 0;
$tests = [];
$tests[] = function() use ($db, $auth) {
$u = $auth->register('t1@[Link]', 'password123', 'Tester');
if (!$db->find('users', $u['id'])) throw new Exception("User not found after register");
$a = $auth->authenticate('t1@[Link]', 'password123');
if (!$a) throw new Exception("Authentication failed");
return true;
};
$tests[] = function() use ($db, $auth, $cs) {
$u = $auth->register('p1@[Link]', 'pwd12345', 'Poster');
$post = $cs->createPost($u['id'], 'Hello World', 'Content body', ['php']);
if (!$db->find('posts', $post['id'])) throw new Exception('Post not created');
$c = $cs->addComment($post['id'], $u['id'], 'Nice post');
if (!$db->find('comments', $c['id'])) throw new Exception('Comment not found');
return true;
};
foreach ($tests as $i => $t) {
try {
$t();
echo "✔ Test " . ($i+1) . " passed\n";
} catch (Exception $e) {
$failures++;
echo "✖ Test " . ($i+1) . " failed: " . $e->getMessage() . "\n";
}
}
echo "Finished tests. Failures: {$failures}\n";
if ($failures > 0) exit(1);
}
}
// -------------------------
// If executed via built-in server (php -S host:port super_long_app.php), route requests
// -------------------------
if (php_sapi_name() === 'cli-server') {
// When using built-in PHP server, this file acts as router.
// Serve static files normally if they exist.
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$full = __DIR__ . $path;
if ($path !== '/' && file_exists($full)) {
return false; // let the server serve the file
}
// Initialize DB with optional sqlite if env set
$useSqlite = getenv('APP_USE_SQLITE') === '1';
$db = new InMemoryDB($useSqlite, 'data/[Link]');
$api = new Api($db);
$req = new Request();
$api->handle($req);
exit;
}
// -------------------------
// If executed from CLI
// -------------------------
if (php_sapi_name() === 'cli') {
CLI::run($argv);
exit;
}
// -------------------------
// End of file
// -------------------------