Construire la liste et la recherche
Objectif : Afficher les contacts enregistrés et filtrer la liste à partir d’un terme de recherche.
Quand votre carnet contient plusieurs contacts, parcourir toute la liste pour retrouver une personne devient fastidieux. Vous allez ajouter une recherche qui filtre les contacts affichés sans modifier les données enregistrées. Le terme de recherche sera transmis en GET : une recherche ne change rien au carnet et peut être répétée en rechargeant la page.
La leçon « Enregistrer les contacts dans un fichier JSON » a isolé le stockage derrière des fonctions partagées : réutilisez la fonction de lecture déjà présente dans includes/fonctions.php, sans lire le fichier de stockage directement dans la page. Les exemples ci-dessous appellent cette fonction lire_contacts() ; si votre projet lui a donné un autre nom, remplacez cet appel par son nom réel, sans changer son comportement.
Préparer les contacts et la recherche
Dans index.php, commencez par charger les fonctions, contrôler l’accès privé, puis préparer la liste avant d’inclure le gabarit. Le paramètre q est lu depuis l’URL. Une vérification garantit qu’il s’agit d’une chaîne ; la fonction trim retire les espaces au début et à la fin. Le filtre compare le terme au nom et au courriel de chaque contact, sans distinguer les majuscules des minuscules.
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/fonctions.php';
exiger_authentification();
$contacts = lire_contacts();
$recherche = filter_input(INPUT_GET, 'q', FILTER_UNSAFE_RAW);
$recherche = is_string($recherche) ? trim($recherche) : '';
$contacts_affiches = $contacts;
if ($recherche !== '') {
$contacts_affiches = array_filter(
$contacts,
static function (array $contact) use ($recherche): bool {
return mb_stripos($contact['nom'], $recherche) !== false
|| mb_stripos($contact['courriel'], $recherche) !== false;
}
);
}
$nombre_contacts = count($contacts_affiches);
require __DIR__ . '/includes/entete.php';
?>
<main class="carnet-principal">
<section aria-labelledby="titre-recherche">
<h2 id="titre-recherche">Rechercher un contact</h2>
<form class="carnet-recherche" action="index.php" method="get">
<label class="carnet-champ" for="recherche">Nom ou adresse e-mail</label>
<input id="recherche" name="q" type="search" value="<?= htmlspecialchars($recherche, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>">
<button type="submit">Rechercher</button>
</form>
</section>
<section aria-labelledby="titre-contacts">
<h2 id="titre-contacts">Liste des contacts</h2>
<p><?= $nombre_contacts ?> résultat(s)</p>
<?php if ($nombre_contacts === 0): ?>
<p class="carnet-message" role="status">Aucun contact ne correspond à votre recherche.</p>
<?php else: ?>
<ul class="carnet-liste">
<?php foreach ($contacts_affiches as $contact): ?>
<li class="carnet-contact">
<h3><?= htmlspecialchars($contact['nom'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></h3>
<p><?= htmlspecialchars($contact['courriel'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
<p><?= htmlspecialchars($contact['telephone'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</section>
</main>
<?php require __DIR__ . '/includes/pied.php';Le gabarit conserve la structure du carnet : les classes employées sont celles du contrat, et les contacts sont présentés dans des éléments carnet-contact. L’inclusion de l’en-tête et du pied reprend le découpage déjà mis en place. Vérifiez que ces fichiers contiennent les balises communes nécessaires et que l’en-tête ne génère pas déjà un second élément main ; adaptez alors le contenu partagé pour que la page n’ait qu’un seul conteneur principal.
Comprendre le filtrage et le résultat
Avec une URL comme index.php?q=marie, le code recherche « marie » dans les champs nom et courriel. mb_stripos renvoie la position de la première occurrence sans tenir compte de la casse ; l’expression !== false permet aussi de reconnaître une occurrence située au premier caractère. array_filter garde uniquement les contacts pour lesquels au moins une comparaison réussit.
Si la recherche est vide, le filtre n’est pas exécuté et toute la liste est affichée. Si aucun contact ne correspond, la page affiche un état explicite plutôt qu’une liste vide. Le nombre de résultats est calculé après filtrage : il représente donc les contacts affichés, et non le nombre total enregistré.
À retenir
- Les paramètres GET conviennent à une recherche qui consulte les contacts sans les modifier.
- Filtrez la liste en mémoire après l’avoir obtenue depuis la fonction de stockage existante.
- Utilisez une recherche insensible à la casse et comptez les résultats après filtrage.
- Réaffichez le terme recherché et échappez toutes les valeurs avant leur insertion dans le HTML.
- Prévoyez un message lisible lorsque la recherche ne renvoie aucun contact.
Dans la prochaine leçon, vous ajouterez les actions permettant de modifier et de supprimer un contact tout en protégeant les opérations de modification.