Dossier de projet - Chrysostome Lanoire

La page est créée Enzo Deschamps
 
CONTINUER À LIRE
Dossier de projet - Chrysostome Lanoire
Dossier de projet
                 Titre de concepteur et développeur d’applications

                                           par

                              Chrysostome LANOIRE

 Abstract In this project, I worked with the technology Symfony to create a com-
mercial website focused on hand-made jewelry named Biju - les bijoux de Juliette
after the name of my client.

Titre RNCP de niveau 6
Concepteur et développeur d’applications
Avril 2021
Dossier de projet - Chrysostome Lanoire
Dossier de projet - Chrysostome Lanoire
Remerciements

    La réalisation de ce projet a été possible grâce au concours de plusieurs personnes
à qui je voudrais témoigner toute ma gratitude.
    Je voudrais tout d’abord adresser toute ma reconnaissance à toute l’équipe de
l’INSTIC, pour leur travail et leur encadrement. Je tiens à remercier en particulier
Faouzi Tchenar, mon professeur principal, pour les bases qu’il m’a transmises tout
au long de ma formation.
    Je souhaite aussi remercier l’équipe médicale qui m’a suivi pendant toute la durée
de ce projet, sans laquelle je n’en serait certainement pas arrivé à bout.
    Je désire également remercier toutes les personnes qui m’ont aidé par le biais
d’Internet, et spécialement Eddy Richard pour sa disponibilité, ses conseils et sa
bienveillance.
    Je tiens à remercier spécialement Juliette pour son accompagnement au quoti-
dien, qui fut essentiel au maintient de ma motivation pendant toute la durée du
projet.
    J’en profite pour remercier tous ceux qui m’ont soutenu, rassuré et motivé aux
moments où j’avais le plus de mal à avancer : mes parents en particulier, mais mes
amis, malgré le confinement.
    Un grand merci enfin à tous mes relecteurs, déjà cités plus haut pour la plupart.

                                          2
Dossier de projet - Chrysostome Lanoire
Table des matières

1 Travail préliminaire                                                                                     8
  1.1 Expression du besoin et formulation du cahier des         charges           .   .   .   .   .   .    8
      1.1.1 Besoin du client . . . . . . . . . . . . . . .      . . . . .         .   .   .   .   .   .    8
              Côté utilisateur . . . . . . . . . . . . . . .    . . . . .         .   .   .   .   .   .    8
              Côté administrateur . . . . . . . . . . . .       . . . . .         .   .   .   .   .   .    9
              Autres . . . . . . . . . . . . . . . . . . . .    . . . . .         .   .   .   .   .   .    9
      1.1.2 Mise en place du cahier des charges . . . .         . . . . .         .   .   .   .   .   .    9
  1.2 Environnement humain et technique . . . . . . .           . . . . .         .   .   .   .   .   .   10
      1.2.1 Environnement humain . . . . . . . . . .            . . . . .         .   .   .   .   .   .   10
      1.2.2 Planification et gestion du temps . . . . .         . . . . .         .   .   .   .   .   .   10
      1.2.3 Environnement technique . . . . . . . . .           . . . . .         .   .   .   .   .   .   11
              Plateformes . . . . . . . . . . . . . . . . .     . . . . .         .   .   .   .   .   .   11
              Git . . . . . . . . . . . . . . . . . . . . . .   . . . . .         .   .   .   .   .   .   11
              Choix de l’IDE . . . . . . . . . . . . . . .      . . . . .         .   .   .   .   .   .   11
  1.3 Spécifications . . . . . . . . . . . . . . . . . . . .    . . . . .         .   .   .   .   .   .   12
      1.3.1 Spécifications fonctionnelles . . . . . . . .       . . . . .         .   .   .   .   .   .   12
              État des lieux . . . . . . . . . . . . . . . .    . . . . .         .   .   .   .   .   .   12
              Analyse . . . . . . . . . . . . . . . . . . .     . . . . .         .   .   .   .   .   .   13
              Wireframe . . . . . . . . . . . . . . . . . .     . . . . .         .   .   .   .   .   .   15
      1.3.2 Spécifications techniques . . . . . . . . . .       . . . . .         .   .   .   .   .   .   16
              La programmation orientée objet . . . . .         . . . . .         .   .   .   .   .   .   16
              L’architecture MVC . . . . . . . . . . . .        . . . . .         .   .   .   .   .   .   17
              Symfony . . . . . . . . . . . . . . . . . . .     . . . . .         .   .   .   .   .   .   17
              Gestion des dépendances . . . . . . . . . .       . . . . .         .   .   .   .   .   .   18
              Twig . . . . . . . . . . . . . . . . . . . . .    . . . . .         .   .   .   .   .   .   18
              MySQL . . . . . . . . . . . . . . . . . . .       . . . . .         .   .   .   .   .   .   19
      1.3.3 Sécurité . . . . . . . . . . . . . . . . . . .      . . . . .         .   .   .   .   .   .   19

2 Réalisation du projet                                                                                   20
  2.1 Premiers pas . . . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   20
      2.1.1 Créations préliminaires . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   20
             La base de données . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   20
             Le projet GitLab . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   20
      2.1.2 Création du projet Symfony . . . . . . . . .          .   .   .   .   .   .   .   .   .   .   21
      2.1.3 Installation des premiers composants . . . .          .   .   .   .   .   .   .   .   .   .   22
      2.1.4 Thème Bootstrap et grandes lignes du front            .   .   .   .   .   .   .   .   .   .   22
             Le thème ”Bootstrap Agency” . . . . . . . .          .   .   .   .   .   .   .   .   .   .   22
             La navbar . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   23

                                          3
Dossier de projet - Chrysostome Lanoire
2.2   Le CRUD (Create, Read, Update and Delete) des bijoux . .              .   .   .   .   .   24
      2.2.1 L’ORM de Doctrine . . . . . . . . . . . . . . . . . .           .   .   .   .   .   24
      2.2.2 Création de l’entité Bijou . . . . . . . . . . . . . . .        .   .   .   .   .   24
              Création . . . . . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   24
              Persistence en base de données . . . . . . . . . . . .        .   .   .   .   .   24
      2.2.3 Génération du CRUD avec Doctrine . . . . . . . . .              .   .   .   .   .   25
              La data fixture pour obtenir des données de travail .         .   .   .   .   .   26
              Accéder aux bijoux . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   26
              Slugs . . . . . . . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   27
      2.2.4 Ajout des images par relation . . . . . . . . . . . . .         .   .   .   .   .   27
              Création de l’entité Image . . . . . . . . . . . . . . .      .   .   .   .   .   27
              Création du service d’upload d’image . . . . . . . . .        .   .   .   .   .   28
      2.2.5 Ajout d’une fonctionnalité : supprimer les images . .           .   .   .   .   .   31
      2.2.6 Refonte des vues générées . . . . . . . . . . . . . . .         .   .   .   .   .   32
              Mise en forme avec Bootstrap des vues edit et new .           .   .   .   .   .   32
              Refonte totale de la vue show . . . . . . . . . . . . .       .   .   .   .   .   33
              Refonte totale de la vue index . . . . . . . . . . . . .      .   .   .   .   .   34
2.3   Gestion des utilisateurs . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   35
      2.3.1 Création de l’entité User . . . . . . . . . . . . . . . .       .   .   .   .   .   36
      2.3.2 Génération du formulaire de login avec Symfony . . .            .   .   .   .   .   36
              Redirections . . . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   37
      2.3.3 Gestion des inscriptions . . . . . . . . . . . . . . . .        .   .   .   .   .   37
              Mise en place du formulaire d’inscription . . . . . . .       .   .   .   .   .   37
              Mailer . . . . . . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   38
      2.3.4 Mise en place des règles de permissions . . . . . . . .         .   .   .   .   .   41
              Accès aux pages . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   41
              Éléments contextuels . . . . . . . . . . . . . . . . . .      .   .   .   .   .   41
      2.3.5 Le login-throttling . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   42
      2.3.6 L’option se souvenir de moi et le mot de passe oublié           .   .   .   .   .   42
2.4   Formulaires de contact . . . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   43
      2.4.1 Création de l’entité Contact . . . . . . . . . . . . . .        .   .   .   .   .   43
      2.4.2 Validation du formulaire avec contraintes . . . . . . .         .   .   .   .   .   43
      2.4.3 Captcha . . . . . . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   44
      2.4.4 Envoi du mail . . . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   44
2.5   Panier et commandes . . . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   45
      2.5.1 Gestion du panier . . . . . . . . . . . . . . . . . . .         .   .   .   .   .   45
              Ajouter des bijoux au panier . . . . . . . . . . . . . .      .   .   .   .   .   45
              Supprimer des bijoux du panier, vider le panier . . .         .   .   .   .   .   47
      2.5.2 Gestion des commandes . . . . . . . . . . . . . . . .           .   .   .   .   .   47
              Saisie des informations . . . . . . . . . . . . . . . . .     .   .   .   .   .   48
              Validation des informations . . . . . . . . . . . . . .       .   .   .   .   .   48
              Paiement (Stripe) . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   48
              Confirmation . . . . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   50
      2.5.3 Gestion des commandes : côté administrateur . . . .             .   .   .   .   .   50
2.6   Mise en production . . . . . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   51
2.7   Pour la suite... . . . . . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   52
2.8   Jeu d’essai du comportement lié à une fonctionnalité . . . .          .   .   .   .   .   52
2.9   Veille sur les questions de sécurité . . . . . . . . . . . . . . .    .   .   .   .   .   56

                                         4
Dossier de projet - Chrysostome Lanoire
A L’entité src/Entity/Bijou.php       58

B La vue show.html.twig               61

C Le service MailerService.php        64

                                  5
Dossier de projet - Chrysostome Lanoire
Compétences couvertes par ce
projet

 Voici la liste des compétences que j’ai mises en oeuvre pendant de mon projet.
 • Concevoir et développer des composants d’interface utilisateur en intégrant les
   recommandations de sécurité
    → Maquetter une application
    → Développer une interface utilisateur de type desktop
    → Développer des composants d’accès aux données
    → Développer la partie front-end d’une interface utilisateur web
    → Développer la partie back-end d’une interface utilisateur web
 • Concevoir et développer la persistance des données en intégrant les recomman-
   dations de sécurité
    → Concevoir une base de données
    → Mettre en place une base de données
    → Développer des composants dans le langage d’une base de données
 • Concevoir et développer une application multicouche répartie en intégrant les
   recommandations de sécurité
    → Collaborer à la gestion d’un projet informatique et à l’organisation de
        l’environnement de développement
    → Concevoir une application
    → Développer des composants métier
    → Construire une application organisée en couches
    → Développer une application mobile
    → Préparer et exécuter les plans de tests d’une application
    → Préparer et exécuter le déploiement d’une application
    → Maquetter une application.

                                       6
Introduction

    The project I am presenting in this report is called Biju, and is available at the
address biju.blue. In spite of having worked alone, this is a real project, for a
real client : I worked for a young woman who creates jewelry in her free time, and
who is called Juliette, thus giving the name of the project : Biju, les bijoux de Juliette.

    I have worked with a technology that I have never studied at school : the PHP
framework Symfony. This has considerably increased the difficulty of the project,
since even though I have started learning Symfony by myself in November, I still
had to learn many things to be able to complete it.

    The main goals of this website is to allow her to show her work, by uploading
her creations, and to allow users to buy them. I tried to fetch inspiration from the
giants in the domain of online shopping, such as Amazon, for things like the design
of the basket, or the ”command tunnel” (the steps to complete in order to place an
order).

    I fully intend to keep maintaining this website for my client in the future. That’s
why all along this project, I have paid particular attention to the details : documen-
ting my code, factorizing it whenever possible by creating services and interfaces,
never inserting inline CSS (using classes instead), and all the other good practices I
know.

                                            7
Chapitre 1

Travail préliminaire

1.1     Expression du besoin et formulation du cahier
        des charges
1.1.1 Besoin du client
    Le client de ce projet est une personne qui fabrique des bijoux dans son temps
libre. L’objectif de ce projet est de lui fournir un site web sur lequel elle pourra
montrer son travail et éventuellement vendre ses bijoux.
    Voici un peu plus de détails sur son besoin. Par souci de clarté, je désignerai
dans la suite le client ”d’artisan”, pour ne pas le confondre avec ses propres clients,
les utilisateurs web.

Côté utilisateur
Acceuil Un utilisateur web doit tout d’abord être accueilli, puis introduit au tra-
vail de l’artisan. Il doit donc se le voir présenter, avec une photographie, et une
sélection de son travail, c’est à dire quelques bijoux. Par ailleurs, l’artisan souhaite
que l’utilisateur ait le moyen de le contacter dès la première page.

Index Il faudra ensuite que l’utilisateur puisse consulter l’ensemble des bijoux,
avec leur nom et leur prix.

Pages individuelles Par l’intermédiaire de cette (ou ces) page(s), on devra pou-
voir accéder à d’avantage d’informations à propos des bijoux. Si l’utilisateur est
intéressé par un bijou, il devra pouvoir aisément accéder à l’ensemble des photogra-
phies du bijou, ainsi qu’à sa description.

Contact Il devra alors se voir proposer à nouveau de contacter l’artisan, mais
cette fois dans le cas où il aurait des questions sur le bijou en particulier.

Panier Ensuite, l’utilisateur devra pouvoir ajouter le bijou qu’il consulte à son
panier. Éventuellement, si le bijou n’est pas unique, l’utilisateur pourra en ajouter
plusieurs à son panier.

                                           8
Commande L’utilisateur pourra ensuite passer commande en validant son panier,
et dans la foulée effectuer le paiement de sa commande. Pour cela, il devra être
authentifié, ce qui nous mène à d’autres besoins :

Authentification L’utilisateur, s’il possède déjà un compte sur le site, doit pou-
voir s’authentifier. Il faudra qu’il puisse le faire à tout moment, mais que lorsqu’il
tente de réaliser une action qui nécessite d’être authentifié, il soit redirigé pour le
faire.

Inscription Si l’utilisateur ne possède pas de compte, il faudra qu’il puisse s’en
créer un. Il devra renseigner une adresse email et un mot de passe, puis par souci
de sécurité un email devra lui être envoyé pour valider son compte.

Côté administrateur
Gestion des bijoux L’artisan devra pouvoir consulter les bijoux qu’il a créé. Il
devra de plus pouvoir en créer de nouveaux et modifier ceux déjà présents (par
exemple ajouter des photographies ou modifier la description).

Contact L’artisan devra pouvoir voir les messages qui lui ont été envoyés par
l’intermédiaire du site, et y répondre.

Commandes Les commandes devront être notifiées à l’artisan, et leur détail devra
lui être disponible. Il devra par ailleurs pouvoir notifier automatiquement l’utilisa-
teur de l’avancement de sa commande (préparation, en cours de livraison).

Autres
Unité graphique Il faudra aussi que l’application web présente un univers gra-
phique cohérent, marqué en particulier d’un logo et de quelques éléments présents
sur toutes les pages.

1.1.2    Mise en place du cahier des charges
   Grâce à l’expression du besoin du client citée précédemment, j’ai pu mettre en
place un cahier des charges, que j’ai ensuite fait valider par l’artisan.

Page d’accueil     La page d’accueil devra comporter :
   • une barre de navigation, arborant le logo et le nom du site, et permettant
      d’accéder à l’ensemble des bijoux, au formulaire de contact, au panier, et à la
      connexion/déconnexion.
   • un message de bienvenue
   • une sélection de bijoux
   • un lien vers l’index des bijoux
   • une présentation de l’artisan
   • le formulaire de contact

                                          9
Index On aura de plus une page index de tous les bijoux, sur laquelle seront
affichés une photographie, le nom et le prix de chaque bijou. On mettra en place un
système de pagination pour ne pas avoir à trop faire défiler la page.

Show La page show contiendra le détail de chaque bijou, avec toutes ses photo-
graphies, sa description complète, et un formulaire de contact dont l’objet aura été
prérempli pour annoncer le fait qu’il s’agit d’une prise de contact à propos d’un
bijou.

Contact Le module de contact devra permettre d’envoyer un email à l’artisan.
Celui-ci pourra ensuite se servir des informations transmises par le formulaire (objet
et adresse email) pour répondre par mail.

Panier Mise en place d’un panier standard, stocké dans les variables de session

Commande Commande stockée en base de données, envoyée par email à l’artisan,
et consultable sur l’interface administrateur, depuis lequel on pourra envoyer les
mails automatiques de suivi de la commande.

Authentification Mise en place d’une page de login et d’une page d’inscription.
Pour pouvoir s’authentifier comme un utilisateur, il faudra au préalable que celui-ci
ait été validé. Pour ce faire, la page d’inscription enverra un email contenant un lien
unique de vérification (limité dans le temps).

1.2     Environnement humain et technique
1.2.1 Environnement humain
    J’ai effectué tout mon projet depuis chez moi, à cause du contexte sanitaire. Ce
projet n’a pas été effectué dans le cadre d’un stage, et je ne dépendais d’aucune
entreprise.
    Pendant mon projet, j’ai principalement intéragi avec mon client (l’artisan), pour
faire valider mon travail et pour recueillir ses suggestions ; et avec divers internautes,
par le biais notamment de forums et de la plateforme Reddit, pour me documenter
et trouver des solutions aux éventuels problèmes que j’ai rencontré.

1.2.2 Planification et gestion du temps
   Étant données les conditions particulières dans lesquelles j’ai travaillé, j’ai dû
m’organsier seul, et cela s’est ressenti directement sur ma planification.
   J’ai utlisé l’outil en ligne Trello pour séparer aussi bien que possible les tâches,
avec les trois colonnes usuelles (To Do, Doing, Done), et un code couleur pour
démarquer l’urgent du moins pressé et le facultatif de l’obligatoire.
   Étant donné que mon projet ne s’inscrivait pas dans le cadre d’un travail en
entreprise ni d’un projet avec l’école, j’ai du le commencer sur mon temps libre. J’ai
ensuite organisé mon travail en fonction des fonctionnalités du projet : je commence
à en concevoir une, et lorsque je suis bloqué j’effectue des recherches sur Internet et

                                           10
si possible je me fais aider par d’autres développeurs ; et, en attendant que je trouve
le moyen de me débloquer, je commence (sur une autre branche, cf section 1.2.3 sur
Git) à programmer une nouvelle fonctionnalité. J’ai pu travailler comme ça sur 2, 3
voire 4 fonctionnalités simultanément.
    L’avancement du projet était principalement marqué par mes merges Git sur la
branche principale, et c’est en me basant sur ceux-ci que je mesurais mon avance-
ment.

1.2.3    Environnement technique
Plateformes
   J’ai travaillé sur plusieurs systèmes d’exploitation. J’ai commencé le projet sur
Windows (10) et Ubuntu (20.04). Je l’ai terminé sous Kali Linux. Et le serveur utilisé
pour la production est sous Ubuntu 16.04. J’ai donc eu l’occasion d’expérimenter
avec les différents outils sous Windows comme sur Linux.

Git
   Afin de développer sereinement mon application, j’ai choisi d’utiliser Git (version
2.29), l’un des outil de versionning les plus utilisés dans le monde du développement
web. Ce dernier présente de nombreux avantages qui m’ont été utiles tout au long
de mon projet :
   • la possibilité de revenir en arrière dans le cas où les dernières modifications ne
      sont pas satisfaisante
   • la possibilité de développer plusieurs couches différentes de mon application en
      parallèle (ne pas être obligé de finir chaque fonctionnalité avant de passer à la
      suivante), à l’aide des branches. J’avais en particulier deux types de branches :
      la branche dev, contenant la dernière version fonctionnelle du code, utilisée
      aussi pour la production, et les branches de toutes les fonctionnalités en cours
      de développement
   • un dernier avantage, que je n’ai pas eu l’occasion d’expérimenter dans mon
      projet : la possibilité de faire valider mon code par un autre développeur (à
      l’aide notamment de merge requests, où la mise à jour de la branche principale
      est soumise à la relecture d’un autre développeur, et à sa validation).
Pour pouvoir utiliser Git comme moyen de télécharger les dernières modifications ap-
portées à mon projet sur mon serveur (pour la production), j’ai utilisé la plateforme
en ligne GitLab, sur laquelle j’ai créé un projet privé.

Choix de l’IDE
   J’ai choisi l’IDE PhpStorm, pour les deux raisons suivantes : d’une part c’est
un IDE qui m’a été recommandé par des développeurs senior pour travailler sur du
Symfony ; et, d’autre part, l’INSTIC me procure une licence gratuitement. Parmi les
fonctionnalités proposées par PhpStorm, on peut notamment citer : autocompletion,
génération automatique de ”PhpDoc” (commentaires de documentation du code),
chargement automatique de dépendances, terminal intégré, plugins pour Symfony,
gestion graphique de Git.

                                          11
1.3     Spécifications
1.3.1 Spécifications fonctionnelles
État des lieux
   Dans un premier temps, afin de visualiser et de mieux comprendre l’expression
du besoin de l’artisan, nous avons réalisé deux diagrammes de cas d’utilisation.
   Voici le premier, qui concerne la partie utilisateur (front-end).

            Figure 1.1 : Diagramme de cas d’utilisation pour l’utilisateur

    On voit sur ce diagramme que les utilisateurs font appel à la base de données
pour afficher les bijoux, se connecter et s’inscrire ; il font de plus appel au client
SMTP (cf section 2.3.3) pour envoyer des mails automatiquement lors de certaines
actions, comme compléter le formulaire de contact ou s’inscrire (email de confirma-
tion de l’adresse email) ou encore passer commande (deux mails : notification de
passage de commande à l’utilisateur et à l’administrateur).

   Voici le second diagramme, celui cette fois de la partie administrateur (back-end).

                                         12
Figure 1.2 : Diagramme de cas d’utilisation pour l’administrateur

   Fort de ces informations et du cahier des charges, j’ai pu élaborer une arbores-
cence du squelette du site. Les pages sont représentées en ignorant les permissions
nécessaires pour y parvenir.

                          Figure 1.3 : Arborescence du site

Analyse
   J’ai pu tirer de la partie précédente les informations nécessaires à la constitution
d’un diagramme de classes (pour les classes ”entités” uniquement, car avec Symfony
beaucoup de fichiers définissent des classes). Le voici :

                                          13
Figure 1.4 : Diagramme de classes des entités du mon projet

   En complément, voici le diagramme de classes des services implémentés tout au
long de mon projet :

             Figure 1.5 : Diagramme de classes des services du projet

                                        14
Wireframe
   Pour la partie graphique, j’ai réalisé un wireframe décrivant pour mon client les
grandes lignes de la disposition de la page d’accueil (que celui-ci a validé). Le voici :

                 Figure 1.6 : Wireframe de la page d’accueil du projet

   Comme décrit dans la partie 2.1.4, j’ai utilisé pour le graphisme du site un
template Bootstrap (le template ”Agency”). Bootstrap est un projet regroupant un
ensemble d’outils (HTML, CSS, SCSS, JavaScript) pour développer des applications

                                           15
web responsive. Pour la maquette, j’ai donc simplement présenté au client le site juste
après avoir mis en place le thème et retiré les parties dont je ne me servirai pas pour
le site (services, about et partenaires).

1.3.2 Spécifications techniques
La programmation orientée objet
    La programmation orientée objet, que j’ai utilisé tout au long de mon projet, est
un paradigme de programmation consistant à regrouper certaines informations liées
entre elles conceptuellement dans des ”objets”. Ces derniers étendent en quelque
sorte la notion de variable : là où une variable est définie par un type et une valeur,
un objet est défini par des attributs (qui eux-mêmes sont soit des variables soit
d’autres objets), et par des méthodes, qui peuvent par exemple être des fonctions,
et qui n’ont de sens qu’en lien avec l’objet dont elles découlent.
    Prenons un exemple tiré de mon projet (j’ai volontairement enlevé une partie
des commentaires et certaines méthodes afin de simplifier pour illustrer de manière
minimale la programmation orientée objet) :
                                                                                         
 1    class Image
 2    {
 3        /**
 4         * @ORM\ Column (type =" integer ")
 5         */
 6        private $id;
 7
 8        /**
 9         * @ORM\ Column (type =" string ", length =255)
10         */
11        private $name;
12
13        /**
14         * @ORM\ ManyToMany (
15         *     targetEntity = Bijou :: class
16         * )
17         */
18        private $ bijous ;
19
20        public function __construct ()
21        {
22            $this -> bijous = new ArrayCollection ();
23        }
24
25        public function getId (): ?int
26        {
27            return $this ->id;
28        }
29
30        public function getName (): ? string
31        {
32            return $this ->name;
33        }
34
35        public function setName ( string $name): self
36        {
37            $this ->name = $name;

                                          16
38
39           return $this;
40       }
                                                                                            
    L’entité Image est ici implémentée par une classe (d’objet). Elle possède trois
attributs : $id, $name et $bijou. Les deux premiers sont des variables (de type ”integer”
et ”string”), et le troisième est un autre objet (de classe ”bijou”).
    Le contructeur __construct est une méthode particulière à la programmation
orientée objet, qui permet d’éventuellement initialiser les attributs de l’objet lors de
sa création.
    Enfin, les ”getters” et ”setters” getId(), getName() et setName() sont tous trois
des méthodes de classe (permettant d’invoquer l’attribut auquel ils sont associés :
pour obtenir la valeur de l’attribut $name d’un objet de la classe Image, le code est :
$objet->getName()).

L’architecture MVC
   L’architecture ”Modèle-Vue-Controlleur”, dite MVC, fait partie des briques de
base sur lesquelles j’ai construit mon projet. Elle consiste en une factorisation du
code bien particulière, reposant sur trois composants principaux : le controlleur, qui
contient le code qui doit être exécuté ; la vue, qui contient le code de la partie visible
du projet (HTML, Twig dans ce projet) ; et enfin le modèle, qui gère les intéractions
avec la base de données.
   On a en résumé le schéma suivant :

                   Figure 1.7 : Schéma récapitulatif du modèle MVC

    Cepandant, tout du long de ce projet, je ferai appel à des fichiers n’entrant dans
aucune catégorie (services, interfaces...). Nous ferons aussi appel de façon implicite
(cf paragraphe 1.3.2 sur Symfony) à un quatrième élément parfois ajouté au modèle
MVC : le routeur.

Symfony
    J’ai décidé pour ce projet de faire appel à un framework de PHP : Symfony. C’est
l’un des deux frameworks majeurs du développement web PHP d’aujourd’hui (avec

                                           17
Laravel).
    Les intérêts d’un tel framework sont multiples : la structure en couches est inté-
grée, la sécurité est un des piliers de Symfony, les bonnes pratiques sont largement
favorisées, l’organisation en services est naturelle, de nombreux bundles sont dispo-
nibles et immédiatement utilisables...
On peut de plus analyser finement les opérations se déroulant sur l’application, grâce
notamment à la ”debug bar” dans l’environnement de développement (qui permet
par exemple d’avoir le détail sur les éventuels codes d’erreur HTTP, sur les mails
envoyés, l’utilisateur connecté, les logs...).
    J’ai utilisé la version la plus récente disponible (Symfony 5). J’ai commencé le
projet avec la version 5.1, et je suis monté par la suite à la version 5.2, en raison
d’une fonctionnalité de sécurité intéressante de cette version (cf partie 2.9 sur le
login-throttling).

Gestion des dépendances
Composer Le gestionnaire de dépendances que j’ai utilisé est bien connu des
développeurs PHP : composer. À l’instar de npm par exemple, composer permet
d’installer et de mettre à jour des dépendances, à l’échelle d’un projet (ce qui le
différencie d’un gestionnaire de paquet, comme apt pour Debian Linux et ses dérivés,
qui eux installent leurs paquets à l’échelle du système).
    Quelques exemples de dépendances que j’ai installées avec composer tout au long
du projet : Webpack encore (cf partie suivante), un composant pour ”slugifier” des
titres en URL, un mailer de Symfony supportant le SMTP...
    J’ai utilisé la version 1.10 de composer.

Yarn, Webpack Encore Là où pour installer et gérer les dépendances PHP,
j’ai utilisé composer, pour les dépendances JavaScript et CSS, j’ai utilisé Yarn et
Webpack Encore. Yarn est une surcouche de npm, le gestionnaire de dépendances
Node JS, présentant quelques différences avec ce dernier, notamment une gestion
améliorée du cache. Webpack Encore est un bundler : il permet de synthétiser et
de minifier tous les assets JS, SCSS, CSS, images... du projet, diminuant ainsi au
maximum le nombre et la longueur des fichiers à lire par l’application.

Twig
    Twig est le moteur de templates que j’ai utilisé tout au long de mon projet. Un
moteur de templates est un outil permettant de simplifier au maximum la partie
traitement associée aux vues (cf 1.3.2 sur le modèle MVC), afin de séparer au
maximum la partie interface graphique de la partie traiement. Twig est en général le
moteur de templates privilégié quand on travaille avec Symfony. Le but d’un moteur
de template est d’intégrer les éléments logiques et les éléments de traitement simple
nécéssaires aux templates (boucles, appel de variables, filtres...). Voici un exemple
très simple de l’intérêt de Twig : on peut considérer le code PHP et HTML suivant,
permettant d’afficher le contenu échappé d’un attribut $name d’un objet de la classe
Bijou :
                                                                               
   
                                                                               

                                         18
Le voici en Twig :
                                                                                         
   {{ bijou .name|e }} 
                                                                                         
   On voit bien par cet exemple l’intérêt d’un moteur de templates optimisé.
   J’ai utilisé Twig 3.0, HTML 5 et CSS 3.

MySQL
    MySQL est le système de gestion de bases de données (SGBD) que j’ai utilisé
pour ce projet. J’ai principalement fait ce choix car c’est le SGBD avec lequel j’ai
le plus d’expérience. Pour pouvoir travailler sur les différentes plateformes citée au
1.2.3, j’ai choisi d’héberger ma base de données sur mon serveur.
    Pour controller le contenu de ma base, j’ai utilisé l’interface en ligne PhpMyAd-
min (version 5.0). J’ai utilisé la version 5.7 de MySQL.
    Pour la sécurité de ma base de données (étant donné qu’elle est accessible di-
rectement via Internet), j’ai bien sécurisé le compte root (avec un mot de passe
aléatoire de 24 caractères de toutes les sortes, accessible par mon gestionnaire de
mots de passe), et j’ai créé un utilisateur spécialement pour la base de données du
projet, qui a tous les droits sur cette base mais sur aucune autre. Ainsi, mes bases de
données ne seraient pas exposées dans le cas d’une attaque ou d’une erreur exposant
mes identifiants (présents en dur dans mon projet Symfony).
    De plus, pour limiter au maximum le risque d’une telle attaque, le fichier .env,
que je commit avec Git, ne contient pas mes identifiants de base de données, ni mes
identifiants SMTP permettants d’envoyer les mails : ces derniers sont dans un fichier
.env.local, qui prime sur le .env, et qui est cité dans mon .gitignore (il n’est pas
commité, et par conséquent une faille de sécurité sur GitLab ne les exposerait pas).

1.3.3    Sécurité
    Je reviens sur toutes les mesures mises en œuvre pour la sécurité dans la partie
2.9. Voici néanmoins quelques éléments essentiels que nous pouvons citer dans cette
partie :
  → La partie administrateur et la partie paiement sont protégées par l’authentifi-
     cation (l’administrateur doit de plus bénéficier d’un rôle spécifique)
  → Dans les formulaires du site accessibles aux utilisateurs, les champs sont vérifiés
     (adresse email valide, code postal ne contenant que des chiffres...) et, quand
     elles sont affichées, les variables dont la valeur a été définie par l’utilisateur
     sont échappées par le moteur de templates.

                                          19
Chapitre 2

Réalisation du projet

2.1     Premiers pas
2.1.1 Créations préliminaires
La base de données
    J’ai créé la base de donnée biju de mon projet à partir de l’interface graphique en
ligne phpMyAdmin. Je m’y suis connecté comme l’utilisateur root (administrateur),
puis j’ai créé la base avec l’encodage utf8_general_ci.
    Je me suis ensuite connecté (via SSH) à mon server, et j’ai lancé l’invité de
commande de MySQL, à nouveau en temps que root.
    J’ai ensuite créé l’utilisateur (appelons le alice). Pour cela j’ai utilisé la commande
suivante :
                                                                                             
   CREATE USER 'alice '@'%' IDENTIFIED BY 'password ';
                                                                                             
   Il est évident que l’utilisateur réel que j’ai créé a un nom et un mot de passe plus
sécurisés.
   J’ai ensuite accordé à alice tous les privilèges sur la base de données avec la
commande suivante :
                                                                                             
   GRANT ALL PRIVILEGES
   ON biju .*
   TO 'alice '@'%'
   IDENTIFIED BY 'password ';
                                                                                             

Le projet GitLab
    J’ai créé sur GitLab (j’avais déjà un compte auparavant) un projet qui me servira
de remote pendant tout mon travail. J’avais ce besoin pour la raison suivante : comme
je ne travaillais pas toujours sur la même machine, c’était un moyen de synchroniser
mes postes. De ce point de vue c’était plus une sécurité, car en réalité j’utilise
un autre outil pour les synchroniser (Syncthing, avec lequel je crée un backup en
temps réel de mes documents sur mon serveur, qui synchronise à son tour les autres
machines). Je pouvais grace à cela avoir l’esprit tranquille, car s’il y avait eu un
problème dans la synchronisation je pouvais toujours effectuer un git pull pour
avoir la dernière version de mon travail.

                                            20
2.1.2    Création du projet Symfony
   J’ai commencé par installer composer, en suivant la documentation en ligne. J’ai
ensuite créé mon projet Symfony à l’aide de la commande :
                                                                                            
   cd chemin /du/ dossier / parent /
   composer create - project symfony /website - skeleton biju
                                                                                            
    Cette commande permet de créer toute la structure (le ”squelette”) de l’applica-
tion Symfony. En voici les pricipaux éléments :
                                           • Le dossier bin contient les éxécutables,
                                               comme le script PHP console (appelé par la
                                               commande php bin/console {...})
                                           • Le dossier config contient tous les fichiers
                                               de configuration des bundles (par défaut, il
                                               contient par exemple services.yaml, packages
                                               /security.yaml ou encore packages/twig.yaml.
                                           • Le dossier migration : j’y reviendrai quand
                                               nous parleront de Doctrine
                                           • le dossier node_modules : j’y reviendrai quand
                                               nous parlerons de Webpack Encore et de
                                               Yarn
                                           • Le dossier public : c’est le dossier qui contient
                                               le fichier index.php, qui va dicter le compor-
                                               tement de l’appication, en interprétant no-
                                               tamment les routes. Il contiendra aussi les
                                               assets (en version compilée) du projet, et en
                                               production le fichier .htaccess nécessaire au
                                               fonctionnement d’Apache.
                                           • Le dossier src contiendra les classes PHP, que
                                               ce soient les contrôleurs, les services, les inter-
                                               faces, les entités... C’est celui qui contiendra
                                               la majorité de mon travail.
                                           • Le dossier templates contiendra les vues (cf
                                               1.3.2 sur l’architecture MVC), ainsi que les
                                               templates d’email (en MJML, cf la partie
                                               2.3.3)
   • Le dossier var contiendra notamment les fichiers de log et le cache de Symfony
   • Le dossier vendor contiendra toutes les dépendances PHP du projet
   • Enfin, parmis les fichiers à la racine du projet, on peut citer notamment
     le fichier .env et le fichier .env.local, qui contiendront les informations de
     connexion à la base de données et au mailer ; le fichier .gitignore, qui régira
     quels fichiers ne seront pas inclus dans Git ; le fichier composer.json, qui contien-
     dra les versions de tous les packages installés pour le projet, par composer ; et
     enfin le fichier package.json, équivalent du composer.json mais pour Yarn.

                                          21
2.1.3 Installation des premiers composants
   Sur chaque système, j’ai installé yarn. La méthode diffère un peu en fonction
de l’OS : en effet, sur une des machines Linux l’installation par le gestionnaire
de dépendances NodeJS npm n’a pas fonctionné, et j’ai donc installé yarn par le
gestionnaire de paquets de la distribution (apt).
   J’ai ensuite installé Webpack Encore, dans le projet cette fois, avec composer.
Pour ce faire, j’ai éxécuté les commandes suivantes :
                                                                                             
     composer require symfony /webpack -encore - bundle
     yarn install
                                                                                             
   Pour finir, j’ai rajouté quelques lignes à la configuration par défaut de Webpack
Encore, dans le fichier webpack.config.js :
                                                                                             
1         . enableSassLoader ()
2
3         . copyFiles ([
4              { from: './ assets /images ', to: 'images /[ path ][ name ].[ hash:8
                  ].[ ext]' },
5              { from: './ assets /fonts ', to: 'images /[ path ][ name ].[ hash:8
                  ].[ ext]' }
6         ])
                                                                                             
La ligne 1 permet d’activer le support du SCSS, dont je me servirai pour le style
de mon projet ; les lignes 3 à 6 spécifient comment copier les assets dans le fichier
public. En particulier, pour optimiser la gestion du cache, les fichiers images et
polices comporteront un hash dans leur nom, qui sera regénéré à chaque fois que je
lancerai la commande yarn dev (ou en production, yarn build).

2.1.4 Thème Bootstrap et grandes lignes du front
    J’ai choisi d’utiliser Bootstrap pour ce site pour les mêmes raisons que celles qui
le rendent si populaire : il est d’abord extrèmement bien documenté ; il est aussi très
simple d’utilisation, d’autant que je m’en suis déjà servi ; et enfin, peut-être le plus
important : il permet d’obtenir une application responsive.

Le thème ”Bootstrap Agency”
    J’ai sélectionné pour le design de la page d’accueil de mon projet un thème
Bootstrap gratuit trouvé sur Start Bootstrap 1 : le thème ”Agency” 2 .
    Celui-ci est composé d’une page unique, séparée en plusieurs parties : accueil,
services, portfolio, about, team, contact. Parmis celles-ci, j’ai choisi de ne garder
que : l’accueil ; le portfolio, qui contiendra les six derniers bijoux créés par l’artisant
sous forme d’image-cards Bootstrap ; la partie team, et enfin la partie contact.
    Pour la partie portfolio, le thème propose d’utiliser des modales Bootstrap pour
aller plus loin et visualiser plus d’informations que l’image-card. J’ai choisi de faire
autrement et de rediriger plutôt vers la page du bijou.
    1. https ://startbootstrap.com/templates
    2. Template prévisualisable en ligne, à https ://startbootstrap.com/previews/agency

                                               22
La navbar
Création du logo J’ai commencé par créer un logo très simple, le nom du site,
”BiJu”, dans une police cursive un peu stylisée, et coloré dans l’esprit du thème du
site : en doré. Voilà le résultat :

                         Figure 2.1 : Premier logo pour le site

   Ce logo apparait dans la barre de navigation (présente sur toutes les pages),
ainsi que dans tous les mails envoyés par l’application. Le fond est transparent pour
pouvoir s’adapter à tous les contextes (par exemple, il est affiché par dessus une
image sur la page d’accueil, et sur un fond clair uni sur l’index des bijoux).

Positionnement de la navbar Le thème Agency propose une barre de naviga-
tion fixe sur l’écran (qui descend lorsqu’on fait défiler la page vers le bas). L’artisan
souhaitait plutôt qu’elle soit fixe sur la page (qu’elle soit masquée quand on fait dé-
filer vers le bas). Pour réaliser cela, j’ai joué sur les propriétés de positionnement de
CSS. J’ai englobé toute la page dans une div de classe wrapper, à laquelle j’ai attribué
le style position: relative et j’ai ensuite attribué à la navbar la classe Bootstrap
position-absolute, qui lui donne le style position: absolute. Avec ces deux éléments,
j’ai bien obtenu une navbar fixe par rapport à la page, et pas à l’écran.

    Pour trouver comment obtenir ce résultat, j’ai commencé par rechercher sur
Internet (en anglais), et ne trouvant pas ce que je cherchais, je me suis tourné vers
le forum Stack Overflow. J’y ai posé ma question en anglais, et j’y ai obtenu une
réponse dans les jours qui ont suivi, également en anglais. Le fil en question peut
être consulté ici 3 .

  3. https ://stackoverflow.com/questions/66049066/stack-navbar-and-the-next-section

                                            23
2.2      Le CRUD (Create, Read, Update and Delete)
         des bijoux
2.2.1 L’ORM de Doctrine
    Doctrine est un projet visant à implémenter en PHP des composants faisant le
lien entre des objets et des éléments de base de données. On peut lire sur le site web
l’introduction suivante :
”The Doctrine Project is the home to several PHP libraries primarily focused on
database storage and object mapping. The core projects are the Object Relational
Mapper (ORM) and the Database Abstraction Layer (DBAL) it is built upon.”
    Je vais principalement utiliser dans ce projet l’ORM. Il me permettra d’intéragir
avec la base de données (je n’aurai besoin d’écrire aucune requête SQL, bien que de
les comprendre pourra être utile pour vérifier mon travail) ; il permettra de plus de
faire le lien objet-table de base de données quand ça sera nécessaire.

2.2.2 Création de l’entité Bijou
Création
   Pour créer une entité avec Doctrine, j’ai utilisé le script console de Symfony. Les
entités sont les classes que je persisterai en base de données (sauf, comme nous le
verrons, l’entité Contact).
Pour ce faire, je lance dans un terminal ouvert à la racine du projet la commande :
                                                                                         
     php bin/ console make: entity Bijou
                                                                                         
Je suis alors le cheminement imposé par la console, au cours duquel je crée les diffé-
rents attributs de ma classe Bijou, en spécifiant leur type, ainsi que les informations
nécessaires à leur persistence en base de données (taille par exemple, pour les types
string, ou encore si la valeur peut être nulle en base de données).
    Pour la classe Bijou, j’ai créé les champs suivants : name, price, description,
created_at. Doctrine crée automatiquement un champ id, de type entier, qui aura
le rôle de clé primaire en base de données. Par ailleurs, j’ajouterai plus tard un
champ images. J’ai mis en annexe A la classe générée à la fin du processus.

Persistence en base de données
    La prochaine étape est de créer une migration. Pour cela, j’utilise la commande
                                                                                         
     php bin/ console make: migration
                                                                                         
    Cette commande crée un fichier de migration dans le dossier migrations. Celui-
ci contient les requêtes SQL qui vont être exécutées lors de la prochaine étape.
Un fichier de migration contient deux fonctions, up et down, (qui correspondent
respectivement à la migration et à l’annulation de celle-ci) qui contiennent elles-
même les requêtes. En voici un exemple :
                                                                                         
1        public function up( Schema $ schema ) : void
2        {

                                          24
3               $this -> addSql ('CREATE TABLE bijou (id INT AUTO_INCREMENT NOT
                     NULL , name VARCHAR (255) NOT NULL , price INT NOT NULL ,
                   description LONGTEXT NOT NULL , created_at DATETIME NOT
                   NULL , images LONGTEXT NOT NULL COMMENT \'(DC2Type:array )
                   \', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4
                   COLLATE `utf8mb4 _unicode_ci ` ENGINE = InnoDB ');
4         }
5
6         public function down( Schema $ schema ) : void
7         {
8             $this -> addSql ('DROP TABLE bijou ');
9         }
                                                                                          
    Une fois que j’ai vérifié que la migration contenait bien tout ce que je voulais,
j’exécute la dernière commande, pour migrer en base de données les modifications :
                                                                                          
          php bin/ console doctrine : migrations : migrate
                                                                                          
    Avec cette commande, la classe est maintenant accompagnée d’une table en base
de données, dans laquelle on pourra persister les objets créés, pour pouvoir par la
suite y faire appel.

2.2.3         Génération du CRUD avec Doctrine
    Un CRUD (Create, Read, Update and Delete) est une structure d’application
côté back-end permettant de gérer les instances d’une entité persistées en base de
données. Dans notre cas, il s’agit de pouvoir créer, appeler (pour afficher), modifier
et supprimer des bijoux en base de données, en passant uniquement par le back-office.
    Il est bien sûr possible de créer un CRUD manuellement, mais Symfony propose,
grâce notamment à Doctrine, d’automatiser la création de la structure. Ainsi, pour
le créer, j’ai simplement eu (une fois l’entité Bijou créée) à exécuter la commande
suivante :
                                                                                          
          php bin/ console make:crud
                                                                                          
    Cette commande fait appel au bundle MakerBundle, qui permet de générer au-
tomatiquement le code associé à certaines fonctionnalités, comme ici le CRUD. Elle
crée dans notre cas un certain nombre de choses :
    • un contrôleur src/Controller/BijouController.php : ce contrôleur contiendra
        toute les routes associées au CRUD, ainsi que toute la logique des différents
        composants. Il contiendra en particulier les fonctions index, new, show, edit et
        delete.
    • les vues index, show, new, edit, _delete_form et _form créées dans le dossier
        templates/bijou   et au format .html.twig.
    • et le fichier src/Form/BijouType.php, qui contient les informations nécessaires à
        la création des formulaires du CRUD.
    Le CRUD est donc maintenant créé. Cependant, il reste quelques détails à régler.
Dans un premier temps, voyons comment générer des bijoux factices pour pouvoir
travailler sans perdre de temps à créer véritablement des bijoux ; nous verrons ensuite
la création de slugs pour embellir les URL ; enfin, nous verrons la gestion des images.

                                            25
La data fixture pour obtenir des données de travail
    Le but des fixtures est de générer de ”fausses” données avec lesquelles on peut
travailler. Il est possible de gérérer des fixtures avec Doctrine. Pour ce faire, on
commence par installer le bundle :
                                                                                           
      composer require --dev orm - fixtures
                                                                                           
    J’ai choisi d’utiliser en plus un autre bundle, qui permet de générer des données
aléatoires de tous les types, utile pour donner des valeurs à tous les attributs des
bijoux : fzaninotto/faker.
    Voici la fixture que j’ai utilisé pour me donner une base de travail pour mon
projet :
                                                                                           
 1    public function load( ObjectManager $ manager )
 2    {
 3        $ faker = Factory :: create ('fr_FR ');
 4        for ($i = 0; $i < 100; $i++) {
 5             $bijou = new Bijou ();
 6             $bijou
 7                 ->setName ($faker -> words (3, true))
 8                 -> setDescription ($faker -> sentences (3, true))
 9                 ->setPrice ($faker -> numberBetween (1, 20))
10             $manager -> persist ($ bijou );
11        }
12        $manager -> flush ();
13    }
                                                                                           
    On voit par exemple que je génère 100 bijoux, et que le nom généré pour les
bijoux sera composé de trois mots aléatoires (tirés je pense du Lorem Ipsum).
    Pour exécuter la fixture, il me reste simplement à exécuter la commande :
                                                                                           
      symfony console doctrine : fixtures :load
                                                                                           

Accéder aux bijoux
    Dans un projet Symfony, la partie modèle de l’architecture MVC est répartie sur
plusieurs fichiers. Parmis eux, les entités et les repositories. Afin de sélectionner les
bijoux souhaités sur les différentes pages, j’ai fait appel à ces derniers. Par exemple,
pour la page d’acceil, je ne souhaite récupérer que les 6 derniers bijoux. Pour cela,
j’ai écrit la fonction suivante dans le fichier src/BijouRepository.php :
                                                                                           
1     public function findLatest (): array
2     {
3         return $this -> findVisibleQuery ()
4             ->orderBy ("p. created_at ", "DESC")
5             -> setMaxResults (6)
6             ->getQuery ()
7             ->getResult ();
8     }
                                                                                           
où la fonction findVisibleQuery récupère tous les bijoux en vente dans la base de
données.

                                           26
Slugs
   Par défaut, la route pour afficher un bijou est définie dans le contrôleur Bijou-
Controller par le commentaire suivant de la fonction show :
                                                                                          
1    * @Route ("/{ id}", name=" bijou_show ", methods ={"GET", "POST"})
                                                                                          
   On souhaiterait que la route soit un peu plus parlante, qu’elle rappelle par
exemple le nom du bijou. Pou ce faire, j’ai choisi d’utiliser le bundle cocur/slugify.
   J’ai donc créé un getter getSlug() comme suit :
                                                                                          
1    public function getSlug (): string
2    {
3        return (new Slugify ())->slugify ($this ->name);
4    }
                                                                                          
    J’ai ensuite simplement modifié la route comme suit :
                                                                                          
1         * @Route ("/{ slug }-{id}", name=" bijou_show ", requirements ={"slug
             ": "[a-z0-9 `-]*"}, methods ={"GET", "POST"})
                                                                                          
    Deux remarques : pour appeler la route dans un template, il suffit d’accéder au
slug avec Twig comme ceci (exemple tiré de la page index des bijoux) :
                                                                              
1    
                                                                              
   Enfin, l’expression régulière permet d’ajouter un peu de sécurité en garantissant
qu’aucun contenu problématique ne peut être inséré dans l ’URL.

2.2.4     Ajout des images par relation
Création de l’entité Image
    J’ai commencé par concevoir les images comme un attribut de type array de la
classe Bijou. Cependant, cette méthode s’est révélée difficile d’utilisation, notam-
ment parce qu’en base de données, l’array était stocké au format JSON, qui est très
peu lisible et donc difficile à manipuler.
    J’ai donc fait le choix de modifier ma conception, à la faveur d’images traitées
comme des objets à part entière, reliées à la classe Bijou par une relation. J’ai choisi
d’établir une relation ManyToMany pour me restreindre le moins possible à l’avenir,
mais j’aurais tout aussi bien pu choisir une relation de type OneToMany.
    Petite précision sur la relation ManyToMany : en Merise, il s’agit d’une relation
de type ”n,n”. Lors de la transcription d’une telle relation de le language de la base
de données, on a alors non pas deux mais trois tables de générées : dans notre
cas, une table image, une table bijou et une table bijou_image, dont les éléments
contiendront deux clés primaires chacun, qui seront aussi clés secondaires associées
aux clés primaires des deux autres tables.
    On aura donc le résultat suivant :

                                          27
Figure 2.2 : MPD de la relation ManyToMany

   Pour mettre en place cette relation, j’ai d’abord créé l’entité Image, par la même
méthode que la dernière fois :
                                                                                          
        php bin/ console make: entity Image
                                                                                          
    Je lui ai ajouté pour l’instant un seul attribut $name (et à nouveau Doctrine a
créé automatiquement un attribut $id).
    J’ai ensuite ajouté un nouvel attribut $image à l’entité Bijou, en appelant à
nouveau le script :
                                                                                          
        php bin/ console make: entity Bijou
                                                                                          
   Au moment de choisir le type, j’ai choisi la relation ManyToMany, et j’ai indiqué
que la classe à associer était la classe Image.

Création du service d’upload d’image
    Il a ensuite fallu créer un service pour uploader les images, et trouver le moyen
de lier les images en base de données à leur fichier image correspondant. Pour cela,
j’ai fait au plus simple : le champ $name de chaque image sera le nom du fichier
uploadé. Il faudra donc établir un nom unique pour chaque image, pour par la suite
renommer le fichier correspondant.

    La première étape a été d’ajouter un champ au formulaire associé aux bijoux :
                                                                                          
1       $ builder
2                   ->add('... ')
3                   ->add('imageFile ', Filetype :: class , [
4                       'multiple ' => true ,
5                       'mapped ' => false ,
6                   ])
7            ;
                                                                                          
    Le code ci-dessus permet d’obtenir un champ d’upload de fichier :

    J’ai ensuite créé le service src/Services/UploaderService.php, dans lequel j’ai uti-
lisé l’injection de dépendance pour appeler le chemin vers lequel je souhaite uploader

                                          28
Vous pouvez aussi lire