Refactor database handling to require PostgreSQL connection, removing fallback to JSON. Implement error handling for database unavailability in key files. Update .env.example to reflect mandatory DATABASE_URL for local development. Remove Firebase configuration and related code from the project.

This commit is contained in:
2026-05-23 10:23:28 +02:00
parent 547778bba5
commit 6577db475a
20 changed files with 823 additions and 789 deletions
+28 -21
View File
@@ -16,10 +16,11 @@ The project is architected to remain extremely lightweight and fast, intentional
- `login.php`: Local profile page for dietary goals and saved favorites (browser storage).
- **Support & Layouts**:
- `partials/`: Contains modular templates (`head.php`, `header.php`, `footer.php`) to maintain a clean DRY structure.
- `helpers.php`: Core PHP utilities containing data formatting helpers and the data access layer for the flat-file database.
- `helpers.php`: Core PHP utilities and the PostgreSQL data access layer for recipes.
- `config.php`: Environment-independent configuration loader which reads runtime secrets from `.env`.
- `assets/fc-local.js`: Browser-side storage for favorites and dietary goals.
- `data/`: Houses `recipes.json`, our flat-file recipe database.
- `data/recipes.json`: Optional seed file only (`php scripts/db-seed.php`), not used at runtime.
- `scripts/schema.sql`: Relational table definitions for recipes.
---
@@ -36,7 +37,7 @@ FlixCooks uses a modern, carefully curated vanilla tech-stack focused on lightni
### ⚙️ Backend & Data
- **Engine**: Vanilla PHP.
- **Database**: PostgreSQL (production/staging) with automatic seed from `data/recipes.json`. Without `DATABASE_URL`, the app falls back to the JSON file.
- **Database**: PostgreSQL only. `DATABASE_URL` is required; without a working DB connection the site returns HTTP 503.
- **Environment**: Custom `.env` variable parser integrated into PHP bootstrap.
---
@@ -56,7 +57,8 @@ Make sure you have the following installed on your local machine:
```bash
cp .env.example .env
```
2. Open `.env` and optionally set **local Postgres** (see [Local Postgres (Docker)](#local-postgres-docker) below).
2. Set **`DATABASE_URL`** in `.env` (required). See [Local Postgres (Docker)](#local-postgres-docker) below.
3. Seed recipes once: `php scripts/db-seed.php` (imports `data/recipes.json` into SQL tables).
### 2. Local Postgres (Docker)
@@ -99,14 +101,17 @@ SELECT slug, data->>'title' AS title FROM recipes, jsonb_to_record(data) AS x(ti
\q -- beenden
```
**DB komplett leeren und neu seeden** (lädt wieder aus `data/recipes.json` beim nächsten Seitenaufruf):
**DB komplett leeren und neu seeden:**
```bash
docker compose -f docker-compose.dev.yml down -v
docker compose -f docker-compose.dev.yml up -d
php scripts/db-seed.php
```
Details zum Schema und Ablauf: Abschnitt unten in dieser README und `helpers.php` → `init_db()`.
**Verbindung prüfen:** `php scripts/db-check.php`
Details zum Schema: Abschnitt unten und `scripts/schema.sql`.
### 3. Start the Development Server
@@ -130,27 +135,29 @@ If you prefer running a full local stack:
## 🗄️ Postgres in diesem Projekt (Kurzüberblick)
FlixCooks nutzt **eine Tabelle** kein klassisches „eine Spalte pro Rezeptfeld“-Schema:
Rezepte liegen in **normalisierten SQL-Tabellen** (kein JSONB-Blob, kein Laufzeit-Fallback auf Dateien):
| Spalte | Typ | Bedeutung |
|-------------|------------|-----------|
| `slug` | `VARCHAR` | Eindeutige ID des Rezepts (URL: `/recipe.php?slug=...`) |
| `data` | `JSONB` | **Gesamtes** Rezept als JSON (Titel, Zutaten, Schritte, i18n, …) |
| `created_at`| `TIMESTAMP`| Erstellzeit |
| `updated_at`| `TIMESTAMP`| Letzte Änderung (wird beim Update gesetzt) |
| Tabelle | Inhalt |
|---------|--------|
| `recipes` | Slug, Zeiten, Hero-URL, Nährwerte, `featured`, `coming_soon` |
| `recipe_translations` | Titel, Beschreibung, Kategorie, Schwierigkeit (EN/DE) |
| `recipe_tags` | Tags pro Sprache |
| `recipe_ingredients` | Zutatenzeilen |
| `recipe_utensils` | Werkzeugzeilen |
| `recipe_steps` | Schritte inkl. Video-URL und Timer |
**Warum JSONB?** Das Rezept ist in PHP/JSON ohnehin ein Objekt. Statt 20+ SQL-Spalten zu pflegen, speichert ihr ein Dokument pro Zeile. PostgreSQL kann in `JSONB` trotzdem indexieren und abfragen (`data->>'title'`), wenn ihr später filtern wollt.
Schema: `scripts/schema.sql`. PHP baut daraus dieselben Arrays wie früher (`i18n.en`, `nutrition`, …), damit Templates unverändert bleiben.
**Ablauf beim ersten Aufruf mit leerer DB:**
**Ablauf:**
1. `config.php` liest `DATABASE_URL` → PDO-Verbindung.
2. `init_db()` in `helpers.php` erstellt `recipes`, falls nicht vorhanden.
3. Ist die Tabelle leer → Import aus `data/recipes.json`.
4. `load_recipes()` liest alle Zeilen, dekodiert `data` zurück zu PHP-Arrays.
1. `DATABASE_URL` in `.env` → Verbindung über `config.php`.
2. Beim ersten Request: Tabellen anlegen (`ensure_recipe_schema()`). Alte JSONB-Tabelle wird einmalig migriert.
3. `load_recipes()` liest per SQL; ohne DB → HTTP 503 (`maintenance/db-unavailable.php`).
4. Admin: `save_recipe()` / `delete_recipe()` direkt in die Tabellen.
**Admin speichern:** `save_recipes()` schreibt nach Postgres **und** aktualisiert `data/recipes.json` als Backup.
**Einmalig Daten laden:** `php scripts/db-seed.php` (aus `data/recipes.json`).
Für **Staging/Production** setzt du `DATABASE_URL` in der jeweiligen Hosting-Umgebung nie Production-Daten in der lokalen Dev-DB mischen.
Für **Staging/Production** nur `DATABASE_URL` in der Hosting-Umgebung setzen nie Production-Daten in der lokalen Dev-DB mischen.
---