171 lines
4.5 KiB
Markdown
171 lines
4.5 KiB
Markdown
# F3 Simple Blog
|
|
|
|
Blog simple avec Fat-Free Framework.
|
|
|
|
## Structure
|
|
|
|
```text
|
|
project/
|
|
├── config.local.ini # Surcharges locales (gitignored)
|
|
├── app/
|
|
│ ├── config.ini # Routes et variables F3
|
|
│ ├── bootstrap.php # Initialisation (DB, session, cache, erreurs)
|
|
│ ├── Controllers/
|
|
│ ├── Helpers/ # Fonctions utilitaires (App.php, Error.php)
|
|
│ ├── Models/ # DB\SQL\Mapper (Post, Media, User)
|
|
│ ├── Services/ # MarkdownService
|
|
│ └── Views/
|
|
├── db/
|
|
│ └── app.sqlite
|
|
├── logs/
|
|
│ ├── app.log
|
|
│ └── php-error.log
|
|
├── public/
|
|
│ ├── assets/ # Sources CSS/JS (servis minifiés via /min/@file)
|
|
│ └── uploads/
|
|
│ └── media/ # Images converties en PNG (sans perte)
|
|
└── tmp/
|
|
├── cache/ # Cache F3 (pages publiques + assets minifiés)
|
|
└── uploads/ # Transit Web::receive() — vidé après chaque upload
|
|
```
|
|
|
|
## Philosophie des dossiers runtime
|
|
|
|
Le projet garde la même logique en local et dans Docker :
|
|
|
|
- `tmp/` = runtime temporaire, recréable
|
|
- `db/` = base SQLite persistante
|
|
- `logs/` = logs persistants
|
|
- `public/uploads/media/` = médias publiés et persistants
|
|
|
|
Autrement dit, `tmp/` peut être vidé sans perte métier. Les données à sauvegarder restent hors de `tmp/`.
|
|
|
|
## Fonctionnalités F3 utilisées
|
|
|
|
- **Routage nommé** — `config.ini [routes]`, `$f3->alias()`
|
|
- **Cache HTTP + serveur** — `$f3->expire()` sur les routes publiques, `Cache::reset('.url')` à la mutation
|
|
- **Assets minifiés** — `Web::minify()` via `AssetController` (`GET /min/@file`)
|
|
- **Upload** — `Web::receive()` avec callback de validation taille
|
|
- **Images** — `Image` (chargement, conversion PNG, dimensions), `Base::write()` pour l'écriture
|
|
- **Markdown** — `Markdown::instance()->convert()`
|
|
- **Slugs** — `Web::instance()->slug()`
|
|
- **Session** — `$f3->set('JAR', …)`, token CSRF dans `SESSION.csrf_token`
|
|
- **Logging** — `Log` de F3 avec fallback `file_put_contents`
|
|
- **ORM** — `DB\SQL\Mapper` : `paginate()`, `copyfrom()`, `cast()`, `find()`
|
|
|
|
## Prérequis
|
|
|
|
### Développement local
|
|
|
|
- PHP 8.3+
|
|
- Composer
|
|
- Extensions PHP : `pdo_sqlite`, `dom`, `gd`, `mbstring`
|
|
|
|
### Déploiement Docker
|
|
|
|
- Docker
|
|
- Docker Compose
|
|
|
|
## Configuration
|
|
|
|
Les paramètres par défaut sont dans `app/config.ini`.
|
|
|
|
Pour surcharger localement ou en production :
|
|
|
|
```bash
|
|
cp config.local.ini.example config.local.ini
|
|
```
|
|
|
|
Réglages minimums conseillés en production :
|
|
|
|
```ini
|
|
[globals]
|
|
app.env=prod
|
|
app.timezone=Europe/Paris
|
|
```
|
|
|
|
Le fichier `config.local.ini` sert uniquement aux surcharges d'environnement. Les chemins runtime restent les mêmes partout :
|
|
|
|
- `tmp/cache/` pour le cache F3 et les assets minifiés
|
|
- `tmp/uploads/` pour les fichiers temporaires d'upload
|
|
|
|
## Développement local
|
|
|
|
```bash
|
|
composer install
|
|
cp config.local.ini.example config.local.ini
|
|
php scripts/install.php
|
|
php -S 127.0.0.1:8080 -t public
|
|
```
|
|
|
|
Ouvre ensuite `http://127.0.0.1:8080`.
|
|
|
|
Créer un compte admin :
|
|
|
|
```bash
|
|
php scripts/create-admin.php admin
|
|
# mot de passe : 10 caractères minimum
|
|
```
|
|
|
|
## Déploiement avec Docker
|
|
|
|
```bash
|
|
cp config.local.ini.example config.local.ini
|
|
# édite config.local.ini (app.env=prod, app.timezone, etc.)
|
|
docker compose up -d --build
|
|
```
|
|
|
|
Docker monte les mêmes dossiers runtime que le développement local. Seuls les répertoires persistants restent séparés de `tmp/`.
|
|
|
|
Si `config.local.ini` n'existe pas, le conteneur démarre avec les valeurs par défaut de `app/config.ini`.
|
|
|
|
Le service écoute sur `http://127.0.0.1:8888`.
|
|
|
|
Créer un compte admin :
|
|
|
|
```bash
|
|
docker compose exec app php scripts/create-admin.php admin
|
|
# mot de passe : 10 caractères minimum
|
|
```
|
|
|
|
## Reverse proxy Caddy
|
|
|
|
### Caddy sur le même hôte
|
|
|
|
```caddy
|
|
blog.example.com {
|
|
encode zstd gzip
|
|
reverse_proxy 127.0.0.1:8888
|
|
}
|
|
```
|
|
|
|
### Caddy dans Docker
|
|
|
|
Si Caddy tourne aussi dans Docker, place-le sur le même réseau que `app` et cible directement le service :
|
|
|
|
```caddy
|
|
blog.example.com {
|
|
encode zstd gzip
|
|
reverse_proxy app:80
|
|
}
|
|
```
|
|
|
|
## Données à sauvegarder
|
|
|
|
- `db/` — base SQLite
|
|
- `public/uploads/media/` — images
|
|
- `logs/` — optionnel
|
|
- `tmp/` — non persistant, recréable
|
|
|
|
## Mise à jour
|
|
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
|
|
## Logs
|
|
|
|
- Applicatifs : `logs/app.log`
|
|
- PHP : `logs/php-error.log`
|
|
- Apache (conteneur) : `docker compose logs -f app`
|