Skip to content

How-to : Publication programmée d'articles ​

Référence FT : FT330 (NENE2-FT/pubschedulelog) — Cycle de vie brouillon/programmé/publié/archivé d'articles, accès aux brouillons réservé au propriétaire, articles publiés publics, déclencheur de publication programmée, 34 tests / 95 assertions PASS.

Ce guide montre comment construire un système de gestion d'articles avec publication différée : les auteurs rédigent des brouillons, les programment pour une heure future, et un job en arrière-plan (ou un appel API) les fait passer à l'état publié.

Schéma ​

sql
CREATE TABLE articles (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    author_id  INTEGER NOT NULL,
    title      TEXT    NOT NULL,
    body       TEXT    NOT NULL DEFAULT '',
    status     TEXT    NOT NULL DEFAULT 'draft',   -- draft | scheduled | published | archived
    publish_at TEXT,                               -- ISO-8601, NULL sauf si programmé
    created_at TEXT    NOT NULL,
    updated_at TEXT    NOT NULL
);

Transitions de statut ​

draft ──publier──► published ──archiver──► archived
  │
  └──programmer──► scheduled ──(temps passe)──► published
  │                   │
  │               déprogrammer
  │                   │
  └───────────────────┘

Uniquement les transitions autorisées — les transitions invalides retournent 409.

Endpoints ​

MéthodeCheminDescription
POST/articlesCréer un brouillon (X-User-Id requis)
GET/articles/{id}Obtenir (brouillon : propriétaire seulement ; publié : public)
PUT/articles/{id}Mettre à jour le brouillon (X-User-Id requis)
POST/articles/{id}/publishPublier immédiatement
POST/articles/{id}/scheduleProgrammer pour une heure future
POST/articles/{id}/unscheduleRetourner à l'état brouillon
POST/articles/{id}/archiveArchiver un article publié
GET/articlesLister (avec filtre ?status=)
POST/publish-dueDéclencher les articles programmés dont publish_at est dépassé

Créer un brouillon ​

php
POST /articles  X-User-Id: 1
{"title": "Bonjour", "body": "Monde"}
→ 201  {"id": 1, "status": "draft", "author_id": 1}

// Pas d'auth → 401

Règles de visibilité ​

php
// Brouillon : propriétaire seulement
GET /articles/1  X-User-Id: 1  → 200   // l'auteur voit son propre brouillon
GET /articles/1  X-User-Id: 2  → 404   // autre utilisateur ne peut pas voir le brouillon
GET /articles/1               → 404   // pas d'auth, brouillon caché

// Publié : tout le monde
GET /articles/1               → 200   // public

Publier et archiver ​

php
POST /articles/1/publish  X-User-Id: 1  → 200  {"status": "published"}
POST /articles/1/archive  X-User-Id: 1  → 200  {"status": "archived"}

// Impossible d'archiver un brouillon
POST /articles/1/archive  X-User-Id: 1  → 409

Programmer ​

php
// Programmer pour dans 1 heure
POST /articles/1/schedule  X-User-Id: 1
{"publish_at": "2026-05-27T15:00:00+09:00"}
→ 200  {"status": "scheduled", "publish_at": "2026-05-27T15:00:00+09:00"}

// Heure passée → 422
POST /articles/1/schedule  X-User-Id: 1
{"publish_at": "2020-01-01T00:00:00Z"}
→ 422

// Déprogrammer → retour à brouillon
POST /articles/1/unschedule  X-User-Id: 1
→ 200  {"status": "draft", "publish_at": null}

Déclencher les articles programmés ​

Un cron job ou un endpoint admin fait passer tous les articles programmés avec publish_at <= now :

php
POST /publish-due
→ 200  {"published_count": 3}

Lister les articles ​

php
GET /articles?status=published      → 200  // public, pas d'auth nécessaire
GET /articles?status=draft  X-User-Id: 1  → 200  // seulement ses propres brouillons

Ce qu'il ne faut PAS faire ​

Anti-patternRisque
Montrer le brouillon à un utilisateur non authentifiéFuite de contenu non publié
Permettre la programmation dans le passéL'article se publierait "immédiatement" via le job déclencheur, contournant la révision
Utiliser now() de l'horloge murale dans les tests pour le déclencheur de programmationLes tests deviennent dépendants du temps ; utiliser un force-insert avec un publish_at passé dans les tests
Suppression physique à l'archivagePerdre la piste d'audit ; utiliser le champ status
Permettre la transition archived → publishedRamène du contenu supprimé ; exiger une re-publication explicite

Publié sous licence MIT.