# Deploy a PHP guestbook with PostgreSQL on Yeeted

A Yeeted sample on the **zero-framework PHP path**: no composer.json, just
`index.php` - exactly what the platform's plain-PHP detection serves.

- **Managed postgres with startup migrations**: `migrations/*.sql` applied in
  order, tracked in `schema_migrations`; the sqlite dev fallback rewrites the
  postgres dialect mechanically.
- **POST-redirect-GET** so a refresh never double-signs; everything rendered
  through `htmlspecialchars`.
- **JSON API beside the HTML** (`/api/entries`) so the tests assert behavior,
  not markup.

Tests: `php tests/test.php` (unit + HTTP via the built-in server) ·
`GUESTBOOK_URL=https://... tests/integration.sh` · `./smoke.sh https://...`.

## Run locally

Install PHP with PDO SQLite and mbstring. PDO PostgreSQL is needed when
`DATABASE_URL` is set. From `php/guestbook-php`:

```sh
php tests/test.php
php -S 127.0.0.1:8000 index.php
```

Open `http://localhost:8000`. With no `DATABASE_URL`, the app stores entries
in `guestbook.db`; `GB_SQLITE` can select another local file. The router
argument is needed so API paths reach `index.php` in the PHP development server.

## Deploy and verify

Follow the [deployment walkthrough](getting-started.md). Deploy this
folder, including `lib.php`, the migrations, and `yeeted.yaml`. Yeeted detects
plain PHP without a Composer manifest and supplies PostgreSQL credentials.
The store applies pending migrations when it is first opened by a request.

```sh
sh smoke.sh "$PREVIEW_URL"
GUESTBOOK_URL="$PREVIEW_URL" sh tests/integration.sh
```

Use the HTML form to sign the guestbook, or send a JSON API request:

```sh
curl -i "$PREVIEW_URL/api/entries" -H 'Content-Type: application/json'   -d '{"author":"Demo reader","message":"Hello from Yeeted"}'
curl -fsS "$PREVIEW_URL/api/entries"
```

A valid API write returns 201; blank author or message returns 400. HTML
form submission redirects with 303 after a successful write. The unit test
script covers the local SQLite-backed path and HTTP behavior.

## What to change before real use

The guestbook accepts public writes and includes no account system or spam
moderation. Add those controls before collecting real entries. SQLite testing
uses a mechanical SQL dialect conversion and does not prove PostgreSQL
compatibility. Coordinate migrations before starting concurrent replicas.

[All examples](index.md) · [Deploy an example](getting-started.md)
