Quand une page ne fonctionne pas, à quelle étape la requête s’est-elle arrêtée ? Ce chapitre vous donne une méthode de diagnostic fondée sur le trajet réel.
Le trajet complet
Une requête traverse une chaîne, pas un fichier magique.
Chaque étape reçoit un objet compréhensible, accomplit une responsabilité limitée et transmet le résultat. Cette chaîne rend l’application observable : un statut, un journal ou un test peut confirmer chaque transition.
Avant PHPAML
Comprenez le protocole que le framework organise.
PHPAML ne remplace pas HTTP : il transforme ses messages bruts en objets et en étapes plus faciles à raisonner. Ces cinq notions permettent de comprendre la suite au lieu de mémoriser un pipeline.
HTTP est un dialogue
Le navigateur et le serveur ne partagent pas directement leur mémoire. Ils échangent des messages. La requête décrit ce que le client souhaite; la réponse décrit ce que le serveur a décidé. Cette séparation explique pourquoi vous devez transmettre explicitement les cookies, les paramètres, le contenu et les en-têtes utiles.
Le serveur n’envoie pas seulement une page. Il envoie d’abord un statut, puis des en-têtes, puis éventuellement un corps. Une API JSON, une redirection, un fichier et une page HTML utilisent le même protocole, mais des contenus et des statuts différents.
Une requête possède une intention
GET demande une représentation sans modifier volontairement la ressource. POST soumet une nouvelle action ou crée une ressource. PATCH modifie une partie; DELETE demande une suppression. Employer les bonnes méthodes rend les routes prévisibles, testables et compatibles avec les outils HTTP.
Deux URL identiques ne désignent donc pas nécessairement la même opération. GET /books affiche la collection, tandis que POST /books crée un livre. Le routeur doit tenir compte du chemin et de la méthode.
HTTP est sans état
Deux requêtes successives sont deux messages indépendants. Le serveur ne sait pas automatiquement qu’elles proviennent du même utilisateur. Une session utilise généralement un cookie comme identifiant, puis retrouve les données correspondantes côté serveur.
Cette propriété est importante pour le débogage. Une page peut fonctionner sans connexion mais échouer avec une session expirée; un cookie absent peut provoquer une redirection avant le contrôleur. Inspectez donc le contexte de la requête, pas uniquement son URL.
Les en-têtes transportent le contexte
Accept indique le format souhaité; Content-Type décrit le corps envoyé; Authorization transporte une preuve d’accès; Cookie rattache une session; les en-têtes de sécurité encadrent le comportement du navigateur.
Ils ne sont pas de simples détails. Envoyer du JSON avec un mauvais Content-Type peut empêcher son décodage. Oublier Cache-Control peut afficher une ancienne réponse. Une politique CSP incorrecte peut rendre le HTML visible tout en bloquant les interactions JavaScript.
Une réponse doit être cohérente
Le contenu, le statut et les en-têtes doivent raconter la même histoire. Une page “Livre introuvable” envoyée avec 200 trompe les tests, les moteurs de recherche et les caches. Un JSON envoyé comme text/html complique les clients.
PHPAML rassemble ces éléments dans Response afin que le contrôleur exprime clairement sa décision. La vue produit le contenu; elle ne devrait pas décider seule du statut HTTP ou envoyer des en-têtes tardivement.
Le navigateur crée la requête
Lorsque vous saisissez /books/42, le navigateur envoie une requête HTTP GET. Elle contient la méthode, le chemin, des en-têtes et éventuellement des cookies. À ce stade, aucun contrôleur n’a encore été choisi.
Inspectez la méthode, l’URL, les paramètres et les cookies dans les outils réseau.
public/index.php démarre PHPAML
Le serveur web dirige la requête vers l’unique point d’entrée PHP. Ce fichier charge le runtime et remet la requête au framework. Il ne doit contenir ni règle métier ni liste manuelle de pages.
Si toutes les pages échouent, vérifiez le serveur, public/index.php et le runtime.
Les middlewares protègent le trajet
Avant le contrôleur, les middlewares peuvent ouvrir la session, appliquer les en-têtes de sécurité, limiter le trafic ou vérifier l’authentification. Chacun reçoit la requête, puis décide de poursuivre ou de répondre immédiatement.
Une réponse 401, 403, 419 ou 429 peut provenir d’un middleware avant le contrôleur.
Le routeur sélectionne l’action
Le routeur compare GET et /books/42 aux déclarations de routes/webapp.php. Le motif /books/{id} correspond et fournit id=42 au contrôleur. Une route doit décrire l’entrée sans contenir le traitement complet.
use App\Controllers\BookController;
Route::get('/books/{id}', [BookController::class, 'show']);Une 404 indique souvent un chemin, une méthode ou un paramètre qui ne correspond pas.
Le contrôleur coordonne
BookController valide l’identifiant, demande le livre au modèle et choisit une réponse. Il traduit donc une intention HTTP en opération applicative, sans devenir lui-même la base de données ou la vue.
final class BookController
{
public function show(Request $request): Response
{
$id = (int) $request->route('id');
$book = Book::find($id);
if ($book === null) {
return Response::notFound();
}
return View::render('books/show', ['book' => $book]);
}
}Journalisez l’entrée validée et le résultat métier, jamais les secrets.
Le modèle fournit le résultat
Le modèle recherche le livre et applique les règles du domaine. S’il n’existe pas, le contrôleur produit une réponse 404. S’il existe, ses données sont transmises à la présentation.
Testez le cas trouvé et le cas absent : ils doivent produire 200 et 404.
La réponse repart vers le navigateur
La vue génère le contenu, Response fixe le statut et les en-têtes, puis les middlewares de sortie peuvent encore compléter la sécurité. Le serveur envoie enfin les octets au navigateur.
Content-Type: text/html; charset=UTF-8Content-Security-Policy: default-src 'self'<h1>The Last Lighthouse</h1>
Vérifiez statut, en-têtes et contenu; une belle page avec un mauvais statut reste incorrecte.
Lire les erreurs
Le statut HTTP raconte ce qui s’est passé.
Aucune route ou aucune ressource
Utilisez 404 lorsque l’URL est inconnue ou que books/42 n’existe pas.
Méthode incorrecte
La route existe, mais pas pour la méthode reçue : POST envoyé vers une route uniquement GET.
Entrée comprise mais invalide
Le formulaire est lisible, mais une valeur ne respecte pas les règles de validation.
Erreur interne
Une exception inattendue empêche la réponse normale. Journalisez le détail sans l’exposer en production.
Atelier guidé
Ajoutez GET /books/{id}.
- Déclarez la route et son paramètre dynamique.
- Créez BookController::show et validez id.
- Retournez 404 lorsque le modèle ne trouve rien.
- Rendez la page avec un statut 200 lorsque le livre existe.
- Testez /books/42, /books/999 et POST /books/42.
Correction et quiz
Expliquez le trajet avec vos propres mots.
La route correspond à GET /books/{id}. Le routeur extrait 42. Le contrôleur valide cette valeur, interroge Book et choisit 404 ou une vue. Response porte ensuite le statut, les en-têtes et le contenu à travers les middlewares de sortie jusqu’au serveur.
Pourquoi POST /books/42 doit-il retourner 405 ?
Parce que le chemin est connu, mais aucune route POST ne l’accepte. Une 404 prétendrait à tort que la ressource ou le chemin est inconnu.
Un middleware peut-il empêcher le contrôleur de s’exécuter ?
Oui. Il peut renvoyer immédiatement une réponse d’authentification, de protection CSRF ou de limitation de trafic. C’est pourquoi le diagnostic commence avant le contrôleur.