Chercher dans la gazette

Exercice 6 sur 7 du chapitre 6 · 150 XP · 5 objectifs vérifiés par des tests

Notions abordées : GET$_GETChaîne de requêtestr_contains()array_filter()

Odette ne retrouve plus l'article sur le concours de soupe, et elle n'a pas envie de parcourir toutes les rubriques. Il faut une recherche : un champ dans l'en-tête, et une page qui affiche les articles dont le titre contient le mot tapé.

Votre mission

  1. Dans templates/mise-en-page.php, dans l'en-tête, juste sous </nav>, ajoutez le formulaire <form class="recherche" method="get" action="…">, qui mène à /recherche (avec Url::vers()). Il contient un champ <input type="search" name="q"> et un bouton « Chercher ».
  2. Dans Redaction, ajoutez une méthode statique chercher(string $mot): array, qui renvoie les articles dont le titre contient $mot, majuscules ou minuscules : « SOUPE » trouve le concours de soupe.
  3. Déclarez la route /recherche. Le mot arrive dans $_GET['q'] : comme pour les annonces, n'acceptez qu'une chaîne, sans les espaces autour. Cherchez seulement si le mot n'est pas vide.
  4. Écrivez le gabarit templates/recherche.php et affichez-le dans une page dont l'onglet s'intitule Recherche — La Gazette de Saint-Glinglin :
    • sans mot : <main class="lecture"> avec <p class="aucun-resultat">Tapez un mot à chercher.</p> ;
    • avec un mot : <h2 class="titre-rubrique">Recherche : « soupe »</h2>, puis <main class="articles"> avec les articles trouvés, ou, à leur place dans ce même <main>, <p class="aucun-resultat">Aucun article ne parle de « soupe ».</p> s'il n'y en a aucun.

Léo vous attend au tournant : le mot cherché est réaffiché dans la page, échappez-le.

Rappel

Un formulaire en method="get" ne met pas ses champs dans le corps de la requête, mais dans l'adresse : /recherche?q=soupe. PHP les range dans $_GET. C'est le bon choix pour une recherche : l'adresse des résultats peut se partager ou se garder en favori. Pour ce qui modifie quelque chose, comme proposer une annonce, on garde POST.

str_contains($texte, $morceau) vaut true si $texte contient $morceau. Pour chercher sans tenir compte des majuscules, on met les deux chaînes en minuscules avant de comparer : str_contains(mb_strtolower($titre), mb_strtolower($mot)). Et pour garder les articles qui correspondent, array_filter() et une fonction fléchée font l'affaire, comme pour le sommaire (exercice 14).