Comprendre round3.php, ligne par ligne

Le même fichier que celui de votre labo, expliqué bloc par bloc : ce qu'il fait, pourquoi il est écrit ainsi, et un exemple qui trace son exécution en direct.

Vue d'ensemble

Ce fichier fait une seule chose : recevoir une question tapée dans un formulaire, et afficher à quel point chacun des 3 documents lui ressemble. C'est le Round 3 de votre histoire — la recherche sémantique.

🧭 Le fichier contient 4 morceaux : une fonction de calcul (cosineSimilarity), une fonction qui simule un embedding (getEmbeddingSimule), une liste de documents, puis le formulaire HTML qui utilise tout ça.

Bloc 1 — cosineSimilarity() : mesurer une ressemblance

1function cosineSimilarity(array $a, array $b): float
2{
3    $dot = $normA = $normB = 0.0;
4    foreach ($a as $i => $x) {
5        $dot   += $x * $b[$i];
6        $normA += $x * $x;
7        $normB += $b[$i] * $b[$i];
8    }
9    return ($normA && $normB) ? $dot / (sqrt($normA) * sqrt($normB)) : 0.0;
10}

Ce que fait chaque ligne

LigneExplication
array $a, array $bLa fonction attend deux vecteurs (deux tableaux de nombres) à comparer.
: floatElle renverra toujours un nombre décimal (le score).
$dot = $normA = $normB = 0.0;Trois compteurs à zéro, remplis pendant la boucle.
foreach ($a as $i => $x)On parcourt le vecteur $a ; $i est la position (0, 1, 2…), $x est la valeur à cette position.
$dot += $x * $b[$i]On multiplie les nombres à la même position dans les deux vecteurs, et on additionne au fil de la boucle — c'est le produit scalaire.
$normA += $x * $xOn additionne le carré de chaque nombre de $a — pour calculer sa « longueur ».
return (...) ? ... : 0.0;Un raccourci d'écriture (opérateur ternaire) qui veut dire : si les deux normes ne sont pas nulles, on divise ; sinon, on renvoie 0 pour éviter une division par zéro.
🌍 Analogie : imaginez deux flèches partant du même point. Le score cosinus mesure si elles pointent dans la même direction (proche de 1), perpendiculaires (proche de 0), ou opposées (proche de -1) — peu importe leur longueur.

Bloc 2 — getEmbeddingSimule() : deviner un vecteur à partir de mots

1function getEmbeddingSimule(string $texte): array
2{
3    $texte = strtolower($texte);
4    if (str_contains($texte, "durée") || str_contains($texte, "dure")
5        || str_contains($texte, "heures") || str_contains($texte, "temps")) {
6        return [0.76, 0.19, -0.27, 0.80];
7    }
8    if (str_contains($texte, "prix") || ...) {
9        return [-0.58, 0.22, 0.68, 0.18];
10    }
11    if (str_contains($texte, "apprend") || ...) {
12        return [0.28, 0.73, 0.38, -0.08];
13    }
14    return [0, 0, 0, 0];
15}

Ce que fait chaque ligne

LigneExplication
strtolower($texte)Met le texte en minuscules, pour que « Durée » et « durée » soient traités pareil.
str_contains($texte, "durée")Teste si le mot « durée » apparaît dans le texte, peu importe où.
|| str_contains(...)« OU » : si n'importe lequel de ces mots est présent, la condition est vraie.
return [0.76, 0.19, -0.27, 0.80];Un vecteur fixe, préparé à l'avance, qu'on renvoie dès qu'un des mots de la catégorie « durée » est détecté.
return [0, 0, 0, 0];Si aucun mot connu n'a été trouvé, on renvoie un vecteur neutre.
⚠️ À bien faire comprendre : ceci n'est pas un vrai modèle d'IA. Un vrai modèle calcule le vecteur à partir du sens de la phrase entière, pas d'une simple recherche de mots. Cette fonction imite le résultat pour que le TP fonctionne sans clé API.

Bloc 3 — $documents : la base de connaissances

1$documents = [
2    ["contenu" => "La formation Laravel dure 40 heures.",
3     "vecteur"  => [0.80, 0.18, -0.30, 0.85]],
4    ["contenu" => "...", "vecteur" => [...]],
5    ["contenu" => "...", "vecteur" => [...]],
6];

Ce que fait chaque ligne

$documents est un tableau de tableaux : une liste, où chaque élément est lui-même un petit tableau avec deux informations — le texte (contenu) et son vecteur déjà calculé (vecteur).

🌍 Analogie : c'est l'armoire de Sami (Round 3 de l'histoire) : chaque tiroir contient une fiche, et l'étiquette collée dessus est déjà son point sur la carte du sens.

Bloc 4 — Traiter la question envoyée par le formulaire

1$texte    = trim($_POST['texte'] ?? '');
2$resultat = null;
3if ($texte !== '') {
4    $vQuestion = getEmbeddingSimule($texte);
5    $resultat  = [];
6    foreach ($documents as $document) {
7        $resultat[] = [
8            'contenu' => $document['contenu'],
9            'score'   => cosineSimilarity($vQuestion, $document['vecteur']),
10        ];
11    }
12}

Ce que fait chaque ligne

LigneExplication
$_POST['texte'] ?? ''Récupère le texte envoyé par le formulaire ; ?? évite une erreur si le champ n'existe pas encore (première visite de la page).
trim(...)Enlève les espaces inutiles au début et à la fin.
if ($texte !== '')On ne calcule rien si la personne n'a encore rien tapé.
$vQuestion = getEmbeddingSimule($texte)On transforme la question en vecteur (Bloc 2).
foreach ($documents as $document)On examine chaque document, un par un.
$resultat[] = [...]On ajoute à $resultat le contenu du document et son score de similarité.

Bloc 5 — e() : la fonction de sécurité

1function e(string $s): string
2{
3    return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
4}

Pourquoi cette fonction existe

Avant d'afficher un texte tapé par l'utilisateur dans la page, on doit le « nettoyer ». Sans ça, quelqu'un pourrait taper du code HTML ou JavaScript dans le champ, qui s'exécuterait dans la page — une faille appelée XSS. htmlspecialchars() transforme les caractères dangereux (<, >, "…) en texte inoffensif.

Règle à retenir : tout texte venant de l'utilisateur ($_POST, $_GET…) doit passer par e() avant d'être affiché dans le HTML.

Bloc 6 — Le mélange HTML / PHP

1<input type="text" name="texte" value="<?= e($texte !== '' ? $texte : "Quel est le tarif ?") ?>">
2
3<?php if ($resultat !== null):
4    $meilleurScore = max(array_column($resultat, 'score')); ?>
5  <?php foreach ($resultat as $r): ?>
6    <span><?= $r['score'] == $meilleurScore ? '✅ ' : '' ?><?= e($r['contenu']) ?></span>
7  <?php endforeach; ?>
8<?php endif; ?>

Ce que fait chaque ligne

ÉlémentExplication
<?= ... ?>Raccourci de <?php echo ... ?> : affiche directement une valeur PHP dans le HTML.
if (...) : ... endif;Syntaxe alternative du if { }, pratique quand on mélange PHP et HTML — plus lisible que des accolades.
array_column($resultat, 'score')Extrait uniquement la colonne « score » de tous les résultats, pour en calculer le maximum juste après.
$r['score'] == $meilleurScore ? '✅ ' : ''Opérateur ternaire : si ce score est le meilleur, on affiche une coche verte, sinon rien.
foreach (...) : ... endforeach;Même idée que le foreach classique, en syntaxe alternative pour le HTML.

Trace en direct : exécutez le code sous vos yeux

Choisissez une question : ce panneau rejoue exactement ce que PHP ferait, étape par étape.

    Quiz de compréhension