Site communautaire de partage de figures de snowboard, développé de A à Z avec Symfony
Projet de formation (OpenClassrooms) : développement complet d'un site communautaire pour apprendre les figures de snowboard, avec Symfony et Doctrine. Authentification par JWT fait maison, gestion de figures en CRUD avec upload de médias mixtes (images et vidéos), espace de discussion par figure, contrôle d'accès par rôle et réinitialisation de mot de passe sécurisée.
Contexte
Projet réalisé en formation (parcours Développeur PHP/Symfony, OpenClassrooms). Cahier des charges fictif : créer pour « Jimmy Sweat » un site communautaire de partage de figures de snowboard, avec un annuaire consultable et modifiable par les internautes et un espace de discussion par figure. Contrainte imposée : aucun bundle tiers autorisé, à l'exception d'un bundle pour générer les données initiales. Le projet incluait aussi la production de diagrammes UML (modèle de données, classes, cas d'utilisation, séquences) et l'organisation du travail en issues GitHub.
Modèle de données
Cinq entités Doctrine : User, Trick, Category, Comment, Media. Une figure appartient à une catégorie et à un utilisateur, possède plusieurs médias (images et vidéos) et plusieurs commentaires. Une image à la une (featured_img) est stockée en relation OneToOne distincte du reste des médias, pour un accès direct sans parcourir la collection complète.
Authentification, contrôle d'accès et vérification de compte
La contrainte « pas de bundle tiers » s'applique aussi à l'authentification : le service JWTService réimplémente à la main la génération et la vérification de token JWT — encodage header/payload en base64url, signature HMAC-SHA256, contrôle d'expiration (durée de validité 3h par défaut). Il sécurise le lien de vérification d'email envoyé à l'inscription, avec possibilité de renvoyer un nouveau lien si le premier a expiré. L'authentification repose sur un UserAuthenticator Symfony natif, avec support du « se souvenir de moi » (7 jours). Les actions sensibles (création, modification, suppression d'une figure) sont protégées par rôle au niveau des contrôleurs, en plus de leur masquage côté interface pour les utilisateurs non autorisés.
Réinitialisation de mot de passe
Flux de réinitialisation par token sécurisé associé à l'utilisateur : demande via le nom d'utilisateur, envoi d'un lien à usage unique, saisie du nouveau mot de passe avec les mêmes règles de validation qu'à l'inscription.
CRUD de figures avec upload de médias mixtes
Le formulaire de création/édition combine une image à la une, une collection dynamique d'images secondaires et une collection dynamique de codes vidéo à intégrer (CollectionType Symfony avec allow_add/allow_delete). L'ajout et la suppression de champs côté client sont gérés en JavaScript natif : lecture de l'attribut data-prototype généré par Symfony, remplacement du placeholder __name__, injection du nouveau champ dans le DOM. Si aucune image à la une n'est choisie explicitement, la première image uploadée est promue automatiquement. Les vidéos intégrées voient leur paramètre d'autoplay neutralisé systématiquement à l'enregistrement (remplacement de autoplay=1/autoplay=true par leur équivalent désactivé).
Espace de discussion par figure
Chaque figure dispose de son propre fil de commentaires, avec formulaire de publication directement sur la page de détail, horodatage automatique et association à l'utilisateur connecté.
Filtrage des figures par catégorie
Sur la page d'accueil, un filtre JavaScript côté client permet d'afficher les figures par catégorie (classe CSS générée dynamiquement à partir du slug), sans rechargement de page, ainsi qu'un filtre dédié pour n'afficher que les figures de l'utilisateur connecté.
Données initiales via Faker
Faker est le seul bundle tiers utilisé, conformément à la contrainte du cahier des charges, pour générer les données de démonstration : 12 figures réparties sur plusieurs catégories, associées à des utilisateurs fictifs — au-delà du minimum de 10 figures demandé.
Note
Un service de traitement d'image (recadrage carré, conversion WebP) a été préparé côté architecture mais reste à raccorder aux contrôleurs, aux côtés d'autres pistes d'évolution notées en fin de développement : modification d'avatar après inscription et gestion de groupes par les utilisateurs.