L'essentiel à connaître
Dans un framework MVC (modèle, vue, contrôleur), chaque requête suit le même chemin. Le routeur relie la méthode HTTP et l'adresse à une action d'un contrôleur, qui demande les données au modèle puis renvoie une vue HTML, ou du JSON (un format texte de données) si un autre programme, comme une application mobile, appelle ton API. Exemple avec Laravel (PHP) : GET /photos/42 appelle la méthode show de PhotoController, qui charge la photo par le modèle Photo et la passe à une vue Blade, un gabarit HTML.
Ce contrôleur, tu ne l'appelles jamais : le framework appelle ton code, alors que tu appelles toi-même une bibliothèque. C'est l'inversion de contrôle (Martin Fowler, 2005). Le modèle passe par un ORM, qui relie tables et objets : avec Eloquent, celui de Laravel, chaque table a sa classe, chaque ligne lue devient un objet. Les tables se décrivent dans des migrations, du code rangé avec le projet et rejoué sur chaque poste.
Chez Laravel, Route::resource('photos', ...) crée les sept routes d'une ressource, dont POST /photos vers store, PUT /photos/{photo} (ou PATCH) vers update et GET /photos/{photo}/edit vers edit, le formulaire de modification ; Route::apiResource retire les deux routes à formulaire, create et edit. Django (Python) appelle « vue » la fonction qui choisit les données, et « gabarit » (template) le HTML qui les met en forme (FAQ de Django).
Un modèle renvoyé par un contrôleur part en JSON avec tous ses attributs, sauf ceux de sa liste Hidden. À l'entrée, create($request->all()) ne garde que les champs de la liste Fillable, parade à l'affectation de masse : un champ is_admin ajouté par un visiteur est écarté. Enfin, where envoie les valeurs à part du SQL, contre l'injection SQL (une saisie qui réécrit la requête) ; whereRaw, où tu colles la saisie, ne protège pas (documentation de Laravel 13.x).
À retenir : dans Blade, {{ $x }} échappe la valeur (< devient <) : un script glissé dans un commentaire s'affiche sans s'exécuter, ce qui bloque la faille XSS ; {!! $x !!} n'échappe rien. Le jeton CSRF (@csrf) d'un formulaire POST est lié à la session : un autre site ne peut ni le lire, ni donc agir au nom de l'utilisateur connecté.
Piège classique : dans une boucle, $article->auteur lance une requête par article, en plus de celle de la liste : pour $N$ articles, $N+1$ requêtes. Article::with('auteur')->get() charge tous les auteurs d'un coup : deux requêtes en tout.
Quiz : teste tes connaissances
Les questions se corsent au fil du quiz : les trois dernières sont les plus piégeuses.
Question 1 : Dans une application MVC, où ranges-tu le code qui lit la table des photos ?
Réponse : C. Le modèle lit et écrit les données ; chez Laravel, c'est la classe Photo. Le piège est D : le contrôleur demande les photos au modèle, sans fouiller la base.
Question 2 : Qui décide que GET /photos/42 sera traité par PhotoController ?
Réponse : A. Le routeur relie méthode et adresse à une action, que Laravel appelle avec le paramètre 42. Le piège est D : le navigateur ne connaît pas tes classes.
Question 3 : Qu'est-ce qui distingue un framework d'une bibliothèque ?
Réponse : D. Tu appelles une bibliothèque quand tu veux ; le framework, lui, mène le déroulement et appelle ton code. B est faux : une bibliothèque est souvent faite de classes.
Question 4 : Avec Eloquent, l'ORM de Laravel, à quoi correspond une classe de modèle ?
Réponse : B. Chaque table a son modèle, qui lit et modifie ses lignes ; une ligne lue devient un objet. Le piège est D : une colonne devient un attribut de cet objet.
Question 5 : Tu ajoutes une colonne legende à la table photos. Pourquoi passer par une migration ?
Réponse : A. La migration, rangée avec le projet, se rejoue sur chaque poste et sur le serveur. B est le piège du mot : elle change la structure des tables, sans copier de données.
Question 6 : Une application mobile appelle ton contrôleur. Que doit-il lui renvoyer ?
Réponse : D. Avec une API, l'affichage se fait chez le client, et le serveur n'envoie que les données. A est faux : une vue Blade fabrique du HTML côté serveur.
Question 7 : Avec Route::resource('photos', ...), quelle action reçoit PUT /photos/42 ?
Réponse : C. PUT ou PATCH sur l'adresse d'une photo appelle update. Le piège est B : edit répond à GET /photos/42/edit et affiche seulement le formulaire.
Question 8 : Pourquoi Route::apiResource ne crée-t-il pas les routes create et edit ?
Réponse : B. Un client d'API envoie ses données directement à store ou à update, sans formulaire. Le piège est C : store et show existent aussi avec Route::resource.
Question 9 : Un commentaire contient <script>alert(1)</script>, affiché par {{ $commentaire }} dans une vue Blade. Que voit le lecteur ?
Réponse : D. {{ }} passe la valeur dans htmlspecialchars, qui change < et > en entités : le script s'affiche sans s'exécuter. A serait vrai avec {!! $commentaire !!}, qui n'échappe rien.
Question 10 : À quoi sert le jeton que @csrf ajoute à un formulaire POST ?
Réponse : A. Un autre site peut faire envoyer un formulaire caché avec la session de ton utilisateur, mais sans ce jeton, qu'il ne peut pas lire : la requête est refusée. B est faux : chiffrer, c'est le rôle de HTTPS.
Question 11 : $email vient d'un formulaire. Quelle requête laisse passer une injection SQL ?
Réponse : C. La saisie est collée dans le texte SQL : une apostrophe ferme la chaîne, et la suite devient du code. B n'est pas plus risqué : un modèle Eloquent envoie lui aussi la valeur à part.
Question 12 : Pour Django, framework web en Python, que contient une « vue » ?
Réponse : B. Pour Django, la vue dit quelles données tu vois, le gabarit comment tu les vois. Le piège est A : ce fichier HTML est le gabarit, ce que MVC appelle la vue.
Question 13 : Tu écris Client::create($request->all()). Pourquoi Laravel te fait-il déclarer une liste Fillable ?
Réponse : A. $request->all() prend tous les champs reçus, même ceux ajoutés à la main ; Laravel écarte en silence ceux hors de Fillable. Le piège est B : les colonnes se créent dans une migration.
Question 14 : Ton modèle Client a une colonne mot_de_passe hachée, sans liste Hidden. Que renvoie return $client; en JSON ?
Réponse : D. Laravel convertit tous les attributs ; seule la liste Hidden en retire. Le piège est A : Fillable filtre ce qui entre en base, pas ce qui sort en JSON.
Question 15 : Article::all() charge 40 articles, puis une boucle affiche $article->auteur->nom pour chacun. Combien de requêtes SQL au total ?
Réponse : C. Une requête pour la liste, puis une par auteur lu : $1 + 40 = 41$. B oublie la première ; A est le compte avec Article::with('auteur')->get().
Sources
- Documentation de Laravel 13.x, en particulier Eloquent : Getting Started et Eloquent : Relationships.
- Documentation de Django 6.1, FAQ : généralités.
- Martin Fowler, InversionOfControl, 26 juin 2005.