Site d'annonces d'emploi

Site d'annonces d'emploi

Dans le cadre de mon projet de stage, j'ai été chargé de la refonte complète du site d'offres d'emploi d'un client. La plateforme originale, développée avec le framework WinDev, devait être migrée vers une solution moderne, maintenable et plus performante basée sur PHP, tout en conservant les fonctionnalités de base et en y ajoutant des améliorations clés.

Mon processus de développement a débuté par la mise en place de l'architecture de base. Les offres d'emploi étaient fournies via un fichier JSON, qui servirait de source de données principale pour l'application. J'ai commencé par créer la page d'accueil, composée de deux éléments majeurs : un formulaire interactif pour le filtrage des offres et une liste dynamique en dessous pour afficher les résultats. Pour permettre aux résultats de recherche d'être facilement partagés ou ajoutés aux favoris, j'ai implémenté la logique de filtrage via des paramètres GET dans l'URL. Cette approche s'est également révélée cruciale par la suite pour préserver la vue de l'utilisateur lors de la navigation entre les pages.

Une fois la liste principale en place, j'ai développé les pages individuelles pour chaque offre, en m'assurant que chaque annonce dans la liste menait correctement à sa propre vue détaillée. À ce stade, l'accent a été mis sur l'expérience utilisateur dans différents contextes. J'ai conçu le site avec un design responsive dès le départ, garantissant une utilisabilité optimale sur ordinateurs, tablettes et mobiles. Une exigence spécifique était d'améliorer « l'imprimabilité » d'une offre ; j'ai donc créé une feuille de style dédiée à l'impression qui masquait automatiquement les éléments non essentiels comme le pied de page et les boutons de navigation, fournissant ainsi une version propre et prête pour le papier.

Lorsque le parcours utilisateur principal était fonctionnel — du filtrage de la liste à la consultation d'une offre, puis au retour — j'ai abordé un détail essentiel d'ergonomie : la persistance de l'état. J'ai fait en sorte que lorsqu'un utilisateur revenait à la liste principale depuis une page d'offre, ses filtres précédemment appliqués étaient automatiquement réappliqués. En complément, j'ai ajouté un bouton « Réinitialiser » au formulaire, qui effaçait tous les filtres actifs et vidait les champs, offrant un moyen rapide de démarrer une nouvelle recherche.

À ce stade, j'ai marqué une pause délibérée pour une phase de refactoring significative. Sachant que l'application serait maintenue par une autre personne à long terme, j'ai méticuleusement revu l'ensemble de mon code. Je me suis concentré sur l'amélioration de la clarté, de la modularité et sur l'ajout de commentaires exhaustifs pour expliquer le « pourquoi » du code, et pas seulement le « comment ». C'est également à ce moment que, après discussion avec le client, j'ai stratégiquement simplifié le design visuel. Tout en conservant les éléments de marque principaux comme les polices et le style des boutons pour la cohérence, l'esthétique générale a été rendue plus générique, permettant à la plateforme d'être facilement réutilisée ou mise en marque blanche pour d'autres clients à l'avenir.

Avec une base de code propre et bien documentée, je me suis tourné vers la sécurité et les finitions front-end. Bien que le site n'écrive pas dans une base de données, j'ai compris l'importance de se protéger contre les attaques de type cross-site scripting (XSS). J'ai mis en place une stratégie de validation à deux niveaux pour le formulaire de filtre : validation côté client pour un retour utilisateur immédiat, et validation robuste côté serveur comme contrôle de sécurité de référence. Pour la liste d'offres elle-même, j'ai ajouté une pagination côté client en JavaScript. Étant donné la taille modérée de la source de données JSON, charger toutes les offres en une seule fois et créer des pages « virtuelles » côté client était la solution la plus pragmatique et la plus performante, évitant des requêtes serveur inutiles. Enfin, j'ai trié les offres d'emploi pour afficher les plus récentes en premier, une fonctionnalité standard et attendue pour tout site d'emploi.

Le défi technique le plus important fut l'optimisation des performances. En utilisant les fonctions de chronométrage intégrées de PHP, j'ai identifié que le décodage du fichier JSON à chaque chargement de page consommait environ 5 ms - une surcharge mineure mais notable et superflue. Pour l'éliminer, j'ai conçu un système de cache côté serveur. Ma solution consistait à créer un fichier de cache sérialisé, stockant les données dans un format natif PHP qui pouvait être lu quasi instantanément. J'ai poussé cette optimisation plus loin en prétraitant les données lors de la génération du cache. Le script triait les offres par date et pré-calculait même le code HTML pour l'affichage de chaque offre dans la liste. Cette stratégie de mise en cache avancée a considérablement amélioré les temps de chargement des pages.

Pour gérer le cycle de vie du cache, j'ai implémenté une vérification simple : si le fichier de cache datait de moins de cinq heures, le site chargeait depuis celui-ci ; sinon, il se rabattait sur le fichier JSON. Pour éviter le problème de « l'utilisateur malchanceux » (où un seul utilisateur subit un long temps de chargement pendant la regénération du cache), j'ai créé un script PHP distinct et autonome. Son unique but était de rafraîchir le cache et il a été conçu pour être déclenché par une tâche cron automatisée, garantissant que le cache soit toujours à jour sans jamais impacter la session d'un utilisateur en direct.

La dernière fonctionnalité demandée était un compteur de vues pour chaque page d'offre. Pour garder une solution simple et en accord avec la nature du projet, basée sur des fichiers, j'ai créé un second fichier JSON pour stocker les nombres de vues, avec les identifiants des offres comme clés. Après avoir testé ce système avec un script PowerShell qui simulait 30 requêtes concurrentes, j'ai été convaincu de sa robustesse pour le trafic attendu du site. En pensant à long terme, j'ai identifié que ce fichier de compteurs grandirait indéfiniment. Pour résoudre ce problème, j'ai ajouté une routine à mon script de mise en cache qui croisait les compteurs avec la liste actuelle des offres actives et purgeait automatiquement les données des compteurs pour les offres qui n'existaient plus.

Lors de la revue finale, le client a demandé que les compteurs de vues ne soient visibles que par lui. Comme le site ne disposait ni de panneau d'administration ni de système d'authentification, j'ai imaginé une solution discrète. J'ai implémenté une logique pour vérifier la présence d'un paramètre GET spécifique dans l'URL. S'il est présent, il crée une variable de session, activant l'affichage des compteurs de vues pour le reste de la visite de l'utilisateur. Cela a permis au client de consulter les statistiques via un lien spécial, tout en gardant l'information cachée des visiteurs ordinaires. Cette touche finale a parfaitement illustré la philosophie du projet : créer une solution non seulement techniquement solide, mais aussi intelligemment adaptée aux besoins opérationnels uniques du client.