185 lines
5.5 KiB
Markdown
185 lines
5.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 publiées (JPG conservé, PNG/WebP normalisés en PNG)
|
||
└── tmp/
|
||
├── cache/ # Cache F3 (pages publiques + assets minifiés)
|
||
└── uploads/ # Transit Web::receive() — nettoyé après chaque upload
|
||
```
|
||
|
||
## Philosophie des dossiers runtime
|
||
|
||
Le projet sépare les données persistantes du runtime jetable :
|
||
|
||
- `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]`, filtre `alias` dans les templates, `reroute('@route')` dans les contrôleurs
|
||
- **Cache HTTP + serveur** — TTL déclarés directement dans `[routes]`, `Cache::reset('.url')` à la mutation
|
||
- **Assets minifiés** — `Web::minify()` via `AssetController` (`GET /min/@file`)
|
||
- **Upload** — `Web::receive()` avec contrôle de taille, puis validation MIME/dimensions côté modèle
|
||
- **Images** — normalisation des médias via GD (`JPG` conservé, `PNG/WebP` convertis en `PNG` pour préserver la transparence)
|
||
- **Markdown** — `Markdown::instance()->convert()` + reconstruction DOM en liste blanche
|
||
- **Slugs** — `Web::instance()->slug()`
|
||
- **Session** — `$f3->set('JAR', …)`, hooks `beforeRoute()` sur les contrôleurs protégés, token CSRF créé seulement sur les vues qui contiennent des formulaires
|
||
- **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 ne monte que les dossiers persistants (`db/`, `logs/`, `public/uploads/media/`) et laisse `tmp/` dans le conteneur pour qu'il reste réellement éphémère.
|
||
|
||
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
|
||
```
|
||
|
||
## Cache public et navigation
|
||
|
||
Les pages publiques (`/` et `/posts/@slug`) restent cacheables parce que leur rendu n'accède ni à la session, ni au token CSRF. La navigation publique affiche donc un lien statique vers la connexion / l'administration, tandis que les vues d'administration restent session-aware.
|
||
|
||
## Médias et limites d'upload
|
||
|
||
- Formats acceptés à l'entrée : `JPG`, `PNG`, `WebP`
|
||
- Taille max du fichier reçu : `10 Mo`
|
||
- Dimensions max : `8000 × 8000 px`
|
||
- Limite de surface : `40 mégapixels`
|
||
- Sortie publiée : `JPG` pour les sources JPEG, `PNG` pour les sources PNG/WebP
|
||
|
||
La médiathèque admin est paginée et le picker dans l'éditeur charge seulement les images les plus récentes pour éviter de charger toute la bibliothèque en mémoire à chaque formulaire.
|
||
|
||
## 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`
|