= nl2br(escape((string) $entry['message'])) ?>
The guestbook
A small PHP app with a real PostgreSQL home.
= escape($pageError) ?>
PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); } $path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/'; if ($path === '/health') { header('Content-Type: application/json'); echo json_encode(['ok' => true], JSON_THROW_ON_ERROR); exit; } try { $db = database(); $db->exec(<<<'SQL' CREATE TABLE IF NOT EXISTS guestbook_entries ( id BIGSERIAL PRIMARY KEY, name TEXT NOT NULL, message TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ) SQL); $count = (int) $db->query('SELECT COUNT(*) FROM guestbook_entries')->fetchColumn(); if ($count === 0) { $seed = $db->prepare('INSERT INTO guestbook_entries (name, message) VALUES (:name, :message)'); $seed->execute(['name' => 'Your host', 'message' => 'Welcome. Sign below.']); } if ($_SERVER['REQUEST_METHOD'] === 'POST' && $path === '/sign') { $name = trim((string) ($_POST['name'] ?? '')); $message = trim((string) ($_POST['message'] ?? '')); if ($name === '' || $message === '') { http_response_code(400); throw new InvalidArgumentException('Add your name and a note.'); } $insert = $db->prepare('INSERT INTO guestbook_entries (name, message) VALUES (:name, :message)'); $insert->execute([ 'name' => mb_substr($name, 0, 60), 'message' => mb_substr($message, 0, 500), ]); header('Location: /', true, 303); exit; } $entries = $db->query(<<<'SQL' SELECT name, message, created_at AT TIME ZONE 'UTC' AS created_at FROM guestbook_entries ORDER BY id DESC SQL)->fetchAll(); } catch (Throwable $error) { error_log($error->__toString()); $entries = []; $pageError = $error instanceof InvalidArgumentException ? $error->getMessage() : 'The guestbook cannot reach its database yet.'; } ?>
A small PHP app with a real PostgreSQL home.
= escape($pageError) ?>
= nl2br(escape((string) $entry['message'])) ?>