Vous êtes sur la page 1sur 31

Automated Food Safety

Labeling System
Application de Gestion Automatisée des Étiquettes et
Contrôle Alimentaire pour le Secteur de la Restauration.

Dossier Projet
Développement Web et Web Mobile
Ricardo Martinho da Cruz
1

1. Liste des compétences couvertes par le projet


Ensuite à ma formation DWWM et stage chez WebForce3 Strasbourg, j’ai développé une
application Full-Stack qui permet l’impression d'étiquettes de contrôle de qualité des denrées
alimentaires dans la restauration. Ce projet à couvert les compétences suivantes du référentiel :

1. Maquetter une application


2. Réaliser une interface web statique et adaptable
3. Développer une interface web dynamique
4. Réaliser une interface utilisateur avec une solution de gestion de contenu
5. Créer une base de données
6. Développer les composants d’accès aux données
7. Développer la partie Back-End d’une application web ou web-mobile
8. Élaborer et mettre en œuvre des composants dans une application de gestion de
contenu ou e-commerce

1.1. Maquetter une application

Afin de réaliser la maquette de l'application, j'ai tout d'abord créé un zoning à la main. Ensuite,
j'ai converti ce zoning en version digitale en créant un wireframe détaillant toutes les
fonctionnalités. Pour cela, j'ai utilisé l'outil FIGMA pour élaborer la maquette finale.
L'idéologie qui a guidé la conception de l'application était de créer un design clean, moderne et
convivial, avec une esthétique minimaliste et des couleurs et images qui n'agressent pas
visuellement les utilisateurs. J'ai également choisi d'utiliser la tendance UI du glass morphisme,
qui est de plus en plus populaire ces dernières années, avec des images de fond de produits
alimentaires dans des contextes naturels. Enfin, il est important de souligner que l'application
sera entièrement tactile pour faciliter son utilisation.
2

1.2. Réaliser une interface web statique et adaptable.

Pour rendre l'interface utilisateur responsive, j'ai dû développer la partie front-end de manière à
ce qu'elle soit adaptable à une version desktop et à une version mobile. J'ai utilisé un script JS
et des éléments media queries pour rendre la navbar latérale totalement responsive. De plus, j'ai
utilisé des propriétés personnalisées pour attribuer des variables CSS à certains éléments, ce
qui permet de modifier facilement ces éléments.

1.3. Développer une interface web dynamique.

Le code HTML de chaque page est intégré dans PHP. Les données sont récupérées à partir de la
base de données grâce à une technique de récupération appelée « data fetching », qui est
effectuée via le modèle, puis le contrôleur respectif. Plusieurs contrôleurs sont dédiés à
l'affichage des données, telles que les catégories et leurs produits sur le tableau de bord
utilisateur. J'ai également créé un contrôleur dédié à toutes les données enregistrées sur
l'étiquette de contrôle de qualité que l'utilisateur souhaite imprimer. Cette procédure utilise un
plugin appelé DOM/PDF, qui est disponible sur Github. Ce plugin utilise un moteur de rendu qui
permet de convertir les mises en page HTML visibles dans le DOM en un fichier PDF (facture
PDF).

1.4. Réaliser une interface utilisateur avec une solution de gestion de


contenu.

J’ai réalisé des fonctionnalités CRD (Create, Read, Delete) pour le catalogue des produits. Seuls
les administrateurs ont le privilège de créer et supprimer des produits. Les utilisateurs avec le
rôle d'administrateur peuvent accéder à la liste de tous les produits via le profil d'utilisateur,
tandis que les autres utilisateurs peuvent uniquement visualiser les produits et imprimer leurs
étiquettes à partir du dashboard principal. Pour cela, le server vérifie le statut d'utilisateur de la
session ouverte et, en fonction de certaines conditions "if", certains hyperlinks sont cachés aux
autres utilisateurs.
3

1.5. Créer une base de données.

La base de données a été créée en MySQL. Après une modélisation de la base de données, j’ai
élaboré toutes les tables, ses relations et contraintes sur phpMyAdmin directement.

Figure 1: L’architecture PHP MySQL.

1.6. Développer les composants d’accès aux données.

L'accès aux données est effectué par le server via le model de requête (query) et le controller
dédié (fetch). Le contrôleur injecte ensuite le code HTML dans la vue (DOM). Les fonctions
utilisées dans les contrôleurs utilisent l'extension PHP PDO (php data objects) et des requêtes
SQL pour sélectionner, créer et supprimer des données dans notre base de données. L'utilisation
de l'extension PDO permet l'utilisation de requêtes paramétrées (PDO::PARAM_STR), qui
assurent une sécurité accrue contre les attaques d'injection SQL lors de la communication entre
la base de données et le serveur.

1.7. Développer la partie back-end d’une application web ou web


mobile.

Le backend de l'application utilise PHP vanilla POO (Programmation Orientée Objet) avec une
architecture MVC (Modèle-Vue-Contrôleur). Avant de commencer la programmation, j'ai créé
une arborescence du projet pour avoir une meilleure visualisation et workflow pendant la
construction du server.
Dans l'architecture du projet, on trouve plusieurs modèles avec des classes différenciées pour
leur propre fonctionnalité. Par exemple, un modèle exclusif pour le fetching des données
nécessaires pour les étiquettes de contrôle de qualité, un modèle exclusif pour la fonctionnalité
4

create et delete, et un autre modèle dédié à toutes les données (catégories et produits) injectées
sur l'interface principale.
Une attention particulière est portée sur le modèle labeldata.php car il effectue un fetch du délai
de décongélation et du délai limite de consommation pour chaque produit de notre catalogue.
Ce délai est présenté avec un format TIME data type dans notre base de données MySQL. Ces
données sont transformées par le contrôleur de manière à indiquer la date maximale de
décongélation et la date de péremption de tous les produits utilisés dans le restaurant en
relation avec le jour et l'heure actuels.
J'ai pris soin de bien documenter mon code pour que les autres développeurs travaillant sur ce
projet comprennent facilement le codage du projet. J'ai utilisé correctement le typage PHP pour
que mon code soit clair et propre. J'ai également nommé les variables, les méthodes et les
classes de manière appropriée et divisé le code pour avoir un code plus réutilisable.

1.8. Élaborer et mettre en œuvre des composants dans une


application de gestion de contenu.

J'ai implémenté différentes fonctionnalités dans mes models et controllers que j'ai testées à
l'aide de la méthode agile pour m'assurer qu'elles fonctionnent comme prévu. L’accès aux
données est sécurisé et les composants prennent en compte le risque d’erreur ou de mauvaise
utilisation. J’ai pu réutiliser cette logique sur différents formulaires.

2. Résumé du projet
Après avoir terminé ma formation en Développement Web et Web Mobile (DWWM) chez
WebForce3, j'ai décidé de créer une interface web Full Stack conforme aux normes du dossier
projet. L'inspiration pour ce projet vient de souvenirs datant de 2016, lorsque j'ai travaillé comme
équipier en cuisine rapide chez McDonald's®, mon premier emploi sur le marché du travail. De
cette expérience, j'ai gardé un intérêt particulier pour l'interface de contrôle de qualité des
denrées alimentaires utilisée dans les cuisines de McDonald's. Il s'agit d'une interface
développée exclusivement pour cette chaîne de restaurants, qui permet d'imprimer des
étiquettes DLC (date limite de consommation) pour tous les produits alimentaires présents
dans une cuisine de franchisé.
Dans ce projet, je souhaite réaliser un système automatisé d'étiquetage et de contrôle de
qualité des denrées alimentaires dans la restauration, que j'ai traduit de l'anglais par
"automated food safety labeling system". Cette interface utilisateur sera accessible via un écran
tactile ou une tablette, permettant au propriétaire, aux managers, aux référents qualité et aux
équipiers de cuisine d'un restaurant d'imprimer des étiquettes de contrôle de qualité de taille A7
à l'aide d'une imprimante thermique.
5

L'interface contiendra un catalogue qui permettra d'ajouter et de supprimer des produits (CRUD)
dans le catalogue. Elle fournira également des informations supplémentaires telles que des
graphiques.
Le contrôle de qualité et l'étiquetage de toutes les denrées alimentaires dans la restauration
respecteront les lois de la République française, le règlement UE nº 1169/2011 du Parlement
européen : article 24 ; et le Code de la consommation : art. L451-1 à L451-8, art. R412-9, art.
R451-1.

“La DLC indique une limite impérative. Elle s'applique à des denrées microbiologiquement très
périssables, et, qui, de ce fait, sont susceptibles, après une courte période, de présenter un danger
immédiat pour la santé humaine.”
- economie.gouv.fr

3. Cahier des charges


Pour ce projet, je crée un scénario fictif dans lequel un propriétaire d'un restaurant bistro
français spécialisé dans les burgers souhaite optimiser son service de cuisine avec une
interface display tactile qui lui permet d'imprimer des étiquettes de contrôle de qualité. Le
propriétaire est conscient de l'importance de l'innovation et souhaite améliorer l'efficacité de
son entreprise grâce aux nouvelles technologies. L'entreprise est composée de cinq personnes :
le propriétaire, un manager, deux chefs cuisiniers et un serveur. Tous les membres du personnel
utilisent l'interface sans aucune difficulté, même si celle-ci est entièrement en anglais.
En termes de gestion de projet, j’ai utilisé la méthodologie Agile pour planifier la technique et la
documentation de l’ensemble de l’application. La planification des sprints, des échéances
quotidiennes et hebdomadaires m'a permis d'être efficace et de réaliser ce projet dans les délais
pré-définis. J’ai utilisé des outils Agile tel que Miro, Microsoft Sticky Notes et Git pour m’aider et
à versionner le programme à chaque phase tout au long de ce processus.

3.1. Expression des besoins

Au niveau des étiquettes de contrôle de qualité dans sa cuisine, le client travaillait auparavant
sur papier. Il a ressenti le besoin de passer au digital pour gagner du temps et avoir un contrôle
plus rigoureux des dates limites de consommation de ses produits.
Grâce à l'interface digitale que je développe, le restaurateur aura une meilleure gestion et
conscience de son catalogue de produits, des dates de décongélation et des dates de
péremption. Cela lui permettra de servir ses clients avec des produits de qualité optimale et de
gagner du temps pendant le service.
6

3.2. Spécifications fonctionnelles du projet

Cette interface utilisateur web doit répondre à plusieurs contraintes fonctionnelles, notamment :
● L'utilisateur doit pouvoir consulter facilement le catalogue des produits ainsi que les
chartes graphiques avec des informations supplémentaires.
● L'utilisateur doit être en mesure d'imprimer des étiquettes de décongélation et des
étiquettes de date limite de consommation.
● L'administrateur doit avoir la possibilité d'accéder à une partie d'administration avec le
privilège de créer et supprimer des produits présents dans le catalogue.
● L'administrateur doit pouvoir aussi créer et supprimer des utilisateurs.

3.3 Spécification techniques du projet

Mon application web est structurée et organisée dans un PHP MVC avec un programmation
objet orienté en relation avec une base de données MySQL.
Mon application web est structurée et organisée en PHP MVC avec une programmation orientée
objet en relation avec une base de données MySQL. Le Front End a été réalisé en CSS pur avec
l'aide de JavaScript pour les animations et les autres fonctionnalités pertinentes telles que les
popups. Sur le serveur, la structure PHP MVC OOP facilite l'ergonomie et le routage de toutes les
requêtes et réponses HTTPS entre l'utilisateur (view) et la base de données (data) :

● Model: partie responsable pour communiquer de façon sécurisée avec la base de


données MySQL pour manager toutes les requêtes data queries (CREATE READ
DELETE).
● View: partie responsable du rendu l’interface utilisateur (UI) de l’application.
● Controller: partie intermédiaire entre la vue et le modèle responsable pour gestion des
requêtes utilisateur et modification de la vue.

Dans les modèles de notre MVC on peut constater que différentes classes ont été créées pour
différentes fonctionnalités. Une classe dédiée à l'affichage des catégories de produits de notre
catalogue, et sur chaque menu catégorie, une autre classe est activée via un slug ‘/$id_category’
pour l’affichage des produits de chaque catégorie sur la vue. Pour les pages ‘add user’, ‘view list
users’ et ‘view list products’, on trouvera également différents modèles avec des classes fetch
dédiées à chaque fonctionnalité.
7

Quand l’utilisateur souhaite imprimer un étiqueté, il sélectionne un produit qui déclenche un


popup JavaScript avec deux options:
● Étiquette “DEFROST”: une étiquette décongélation indiquant la date limite entre la sortie
du produit d' une température négative et le moment maximal où ce produit peut être
conservé à une température de réfrigération ( normalement au-dessus de 0º C).
● Etiquette “EXPIRATION”: cette étiquette indique la date limite de consommation du
produit, la date de péremption.
Le délai (timelapse) de chaque produit est stocké en MySQL sous forme des données de type
TIME. Après un requete fetch, les valeurs TIME sont transformées en fonction de la date
actuelle.

Figure 2: Gane
Sarson Data Flow
Model Diagram
(structure server,
entités et actions)>

3.4 Technologies utilisées.

PHP 8: Hypertext Proprocessor est la langage base du projet. Php est une langage de script
server side reconnu dans toute le monde web dans la construction full stack de sites web et des
applications. Php facilite l'intégration du front end avec Html. Dans notre projet, je fait recours à
de la programmation orientée objet avec une structure MVC.

HTML5 : Hypertext Markup Language est un langage de balisage pour représenter la structure
et le contenu d’une page.

CSS3: La dernière version du langage de feuilles de style en cascade . Il s'agit d'un langage
utilisé pour décrire la présentation visuelle des documents HTML.
8

JavaScript: Un langage de programmation utilisé pour ajouter des fonctionnalités interactives à


un site web. Pendant le projet, j’utilisé JS pour créer des animations popup et pour mettre en
évidence les éléments de la barre de navigation sélectionnés par l'utilisateur. JS est essentiel
pour améliorer l'expérience utilisateur et rendre l' interface plus dynamique.

MySQL: Un système de gestion de base de données relationnelle open source. MySQL utilise le
langage de requête SQL (Structured Query Language). Ce système est utilisé pour stocker et
organiser des données entre tables et ses relations. J’utilisé PHPmyAdmin pour faciliter la
gestion de la base de données.

Figure 3: Database
Model MySQL print
(table et relations)

DOM|PDF: Une bibliothèque PHP open-source qui permet de convertir des documents HTML en
PDF. Elle est largement utilisée pour générer des factures et d'autres types de documents en
format PDF à partir de contenu dynamique généré par des applications web. DOM|PDF est une
solution pratique pour générer des fichiers PDF avec une certaine flexibilité de personnalisation.

GIT: Un système de contrôle de version open source qui a permet de suivre les modifications
apportées à un projet de développement de logiciel.

3.5 Design.

L'absence de frameworks front-end a été intentionnelle pour permettre une projection plus
créative et une attention visuelle accrue de la part du développeur. Avant l'intégration visuelle du
projet en code, une étude a été menée sur la palette de couleurs et la typographie. J'ai
commencé par réaliser un zoning wireframe et une maquette conséquente sur Figma afin
d'améliorer le développement visuel du logiciel. Les images de fond utilisées sur plusieurs
pages de ce projet ont été individuellement travaillées sur Figma et parfois sur Adobe
9

Photoshop avant d'être exportées et intégrées dans le projet. Dans notre dossier principal du
projet MVC, il y a un dossier /assets dédié au contenu statique de notre page, tel que les polices,
les CSS, les images, les images de produits, ainsi que les scripts JS.
L'idéologie derrière le design et l'esthétique de l'application était de créer un design propre,
moderne, convivial, minimaliste et pratique avec des couleurs et des images qui ne fatiguent
pas visuellement les utilisateurs. J'ai également utilisé le glass morphism, une tendance UI des
dernières années, avec des images de fond de produits alimentaires dans leur contexte naturel.
Les images de produits présentées sur chaque menu catégorie sont de la responsabilité de
l'administrateur. Les images ont une grande visibilité sur les menus car cette application est
destinée à être utilisée sur des écrans tactiles. Pour le responsive design, une balise meta a été
implémentée pour bloquer le viewport en mode paysage à partir d'une certaine résolution
d'écran. Cette application sera principalement utilisée sur des écrans tactiles et des tablettes en
mode horizontal par le propriétaire du restaurant, les chefs de cuisine et le reste du staff.
Cette application a bénéficié d'un redesign ou d'une amélioration visuelle après la fin du
développement total dans certaines pages. La figure 2 correspond à la version 1.2 de cette
interface.

Figure 4: Maquete (design responsive inclus).


10

3.6 Sécurité

Le projet est à destination du personnel du restaurant en cause et ne doit donc être accessible
que par lui. L’application intègre plusieures mesures de sécurité:

● Système d'authentification et autorisation : Chaque fois qu'un utilisateur souhaite se


connecter, son identité est vérifiée en fonction des données stockées dans la table des
utilisateurs de MySQL. Pour cela, l'application utilise une requête prepare avec
l'extension PDO pour vérifier la présence du nom d'utilisateur. Le mot de passe est vérifié
en récupérant la ligne correspondant à l'utilisateur de la table des utilisateurs et en
utilisant la fonction PHP password_verify(). Si les conditions ne sont pas remplies, un
message d'erreur est affiché.

● Password hashing: Pendant l’enregistrement d' un nouvel utilisateur, les passwords


personnelles de toutes les utilisateurs sont encryptés à l’aide de l'algorithme ARGON2i
dans la base de données. Les mots de passe doivent également respecter des critères
de sécurité strictes, tels qu'une longueur minimale et maximale de caractères,
l’utilisation limitée de caractères spéciaux, entre autres.

● Contrôle de session: Chaque fois qu’un utilisateur se connecte à l'interface, une nouvelle
session est ouverte. Le contrôle de session vérifie le statut de l’utilisateur et lui attribue
un paramètre de rôle. L’administrateur a accès à certaines fonctionnalités exclusives qui
sont limitées aux autres utilisateurs, comme la possibilité d'enregistrer un nouvel
utilisateur ou de créer / supprimer de produits du catalogue du restaurant. Cette mesure
de sécurité empêche le hijacking de session et d’autres vulnérabilités.

● Validation et filtrage de données: Afin d'éviter des attaques d’injection SQL, XSS et
autres vulnérabilités, tous les champs de formulaire input sont sécurisés. Pour cela,
certaines conditions sont vérifiées pour le champs input de type text, telles que la
longueur minimale et maximale des caractères, l’utilisation limitée de caractères
spéciaux, ainsi que la conversion des caractères spéciaux en entités HTML
(htmlspecialchars). Les données insérées sont également filtrées (sanitization) en
11

utilisant une fonction PHP trim(). Dans le formulaire add user, le format d’adresse e-mail
est également vérifié avant l’envoi des données en utilisant FILTER_VALIDATE_EMAIL.

● PDO (PARAM QUERIES): L’utilisation de requêtes / queries paramétrées avec l’extension


PDO permet la communication sécurisée entre les classes du serveur et la base de
données, en évitant les attaques d' injection SQL.

● Upload de fichiers sécurisé : Lorsque l'utilisateur dispose du statut d'administrateur, il a


accès au formulaire Add product qui comprend un champ "input" de type fichier. Afin de
prévenir le téléchargement d'un fichier malveillant (par exemple, un fichier PHP), le
contrôleur dédié vérifie l'extension du fichier en utilisant la fonction
PATHINFO_EXTENSION. Dans notre application, seules les extensions de fichiers .jpg,
.jpeg et .png sont autorisées. Si les conditions ne sont pas satisfaites, un message
d'erreur est affiché.

● Sécurité CSRF (Cross-Site Request Forgery): Lorsqu’un utilisateur se connecte a


l’interface, un token de valeur aléatoire est généré est stocké dans la variable de la
session ouverte. Le valeur de ce token est requise pendant la soumission (submit) de
tous les formulaires présents dans l’appli. Si le token n’est pas présent ou si sa valeur ne
correspond pas, un message d' erreur est affiché ou l’utilisateur est redirigé vers le
formulaire d' inscription.
Une deuxième mesure de sécurité est également implémentée pour renforcer contre les
attaques CSRF. Lorsque l’utilisateur se connecte à l'interface, un deuxième token est
généré. Ce token est stocké dans le browser de l’utilisateur sous forme de cookie
PHPSESSID avec un durée de vie de 4 heures. Ce cookie reste stocké dans le browser et
sur le server jusqu'à l'expiration de session.

4. Extraits de code

4.1 Fetch - injection de HTML (category/product cards)

Après la connexion de l'utilisateur, Il est redirigé vers la page principale de notre dashboard,
home.php. Cette page affiche toutes les catégories de produits disponibles. Sur cette page
principale, on met en disposition toutes les catégories de produits disponibles.
Pour récupérer les informations depuis la base de donnée, une classe CategoriesData, qui
effectue une requête fetch sur la table category.
12

Fig.5 - extrait model/display_data.php

Les données sont ensuite récupérées afin d'être traitées avant l’injection. Cependant, il convient
de noter que le style de toutes les cartes catégorie générées est appliqué dans le contrôleur et
non dans le fichier CSS principal, afin d'éviter certains bugs de stylisation rencontrés pendant la
réalisation de l'interface.
13

Fig.6 - extrait controller/manage_product.php

Le contrôleur organise les cartes catégories qui seront injectées sur le dashboard sous forme
de hyperlinks. Chaque carte redirige l'utilisateur vers le menu des produits correspondant via
une slug méthode GET.

Fig.8 - home.php (central page dashboard)

Fig.7 - extrait home.php


14

Pour l’affichage de tous les


produits en accord avec la
catégorie choisie, je commence
par réaliser une classe
DisplayProduct (model) qui
effectue une requête fetch.
Pour cela, la fonction
get_products($category_id)
utilise une requête prepare avec
des conditions et relations entre
les tables MySQL.

Fig.9 - extrait
model/display_data.php >

Similaire au contrôleur que nous avons vu précédemment pour les cartes de catégories, le
contrôleur display_products.php est également responsable de la structure de toutes les cartes
produits en fonction de la catégorie choisie par l'utilisateur.
Pour cela, la fonction get_products() accepte l'ID de la catégorie en tant qu'argument. L'ID de la
catégorie choisie est stocké dans l'URL lorsque l'utilisateur sélectionne le menu souhaité, puis
récupéré à l'aide de la superglobale $_GET. La boucle foreach parcourt chaque ligne du tableau
"products" pour afficher chaque ligne en tant que carte produit sur notre interface.
Remarque : Toutes les balises CSS sont incluses sur chaque carte directement dans le
controlleur afin d'éviter les problèmes de mise en forme rencontrés lors du développement du
projet. Le style de chaque carte ne peut pas être défini avant l'injection des données dans la vue.
Un autre problème a également été rencontré avec les popups JavaScript, car chaque fenêtre
popup possède deux boutons avec différents hyperlinks (href) en fonction de la slug. La fenêtre
popup <div class="popup"> est déclenchée lorsque l'utilisateur clique sur la carte et se ferme
immédiatement après que l'utilisateur ait sélectionné le type d'étiquette à imprimer.
15

Fig. 10 - extrait
controller/display_product.php

Fig. 11 - products.php + JS popup >


16

4.2 Fetch - injection HTML (étiquette) DOM/PDF

Pour l'impression de l'étiquette, l'utilisateur clique sur la carte du produit souhaité. Une fois la
fenêtre popup est déclenchée, il a le choix entre deux types d'étiquettes : "defrost label" ou
"expiration date".

Avant de commencer le
développement de cette
fonctionnalité, j'ai réalisé une
maquette de l'étiquette afin de
comprendre les données
nécessaires selon les
demandes du client.

Fig.12 - maquette de l' étiquette “expiration date”.

Lors de l'enregistrement d'un produit, l'utilisateur sélectionne, dans le formulaire "add product",
le temps de décongélation (le délai maximum entre la sortie du produit d'une température
négative jusqu'au moment où le produit atteint une température positive de 0ºC) ainsi que le
délai maximum du produit à température ambiante (durée de conservation du produit
alimentaire). Pour cela, le client a utilisé une liste déroulante <select> avec différentes options
de délai.
Chaque option de la select box envoie des données numériques au format "XX:XX:XX". Dans la
base de données, ces valeurs sont interprétées comme des donnés du type TIME

Fig.13 - extrait table products sur mysql (valeurs TIME)

Après avoir créé le formulaire "add product", j'ai également créé une classe dédiée aux données
utilisées pour l'étiquette (modèle). La classe ProductLabelData possède une fonction
get_product_data() qui accepte l'argument $product_id. Cette fonction effectue une requête
pour récupérer toutes les données du produit correspondant à son ID.
17

Fig.14 - extrait /model/label_data.php


Après la récupération des données (fetch), celles-ci sont envoyées au contrôleur
"label_data.php". À l'aide de la méthode GET, la variable $id_product va récupérer l'ID du produit
stocké dans l'URL et l'appliquer en tant qu'argument de la fonction
get_product_data($product_id). Les données sont maintenant accessibles dans un tableau
array.

Fig.15 - extrait
/controller/label_data.php
18

Nous parvenons maintenant à récupérer les données stockées dans la base de données,
notamment les délais de décongélation et la durée de vie de tous les produits alimentaires
définis par l'administrateur de l'application. Ces données doivent maintenant être transformées
afin de nous indiquer la date et l'heure de chaque délai en fonction de la date et de l'heure
actuelles.
Pour cela, les données du type TIME sont soumises à la fonction php explode(), qui accepte les
deux points “:” , le séparateur qui divise la chaîne numérique, comme le premier argument et
ensuite la variable qui contient la chaine numerique comme deuxieme argument.
La fonction php explode() prend chaque valeur numérique de la chaîne fractionnée pour les
organiser dans un tableau array. Ainsi, la première fraction correspond aux heures, le deuxième
aux minutes et le troisième aux secondes de notre temps (TIME). (voir chap 5.2)
Ensuite, nous effectuons un calcul pour représenter les données TIME en secondes. La première
partie (heures) est multipliée par 3600 (le nombre de secondes dans une heure) et la deuxième
partie (minutes) est multipliée par 60 (le nombre de secondes dans une minute). Ensuite, nous
ajoutons le résultat de l'addition des trois parties en secondes avec la fonction PHP time().
Cette addition permet d'ajouter les délais de décongélation ou le temps de consommation
maximum avant la péremption du produit alimentaire choisi à la date courante en secondes -
time().
Pour terminer, nous prenons ce résultat dans une variable et l'appliquons à la fonction date()
(pour obtenir la date et l'heure actuelles) afin d'obtenir la date et l'heure maximales de
décongélation ainsi que la date et l'heure de péremption du produit alimentaire choisi par
l'utilisateur. Ces informations seront affichées sur l'étiquette.

Cette conversion a été initialement


programé en procédurale, puis
transformée en orientée objet avec la
création d'un contrôleur et d'une classe
TimeToDate.

< Fig. 16 - extrait /model/TimeToDate.php


19

Fig. 17 - extrait /controller/

label_data.php

Après avoir effectué quelques recherches, j'ai décidé d'utiliser DOMPDF, un plugin open source
GitHub et une bibliothèque PHP qui permet de convertir des fichiers HTML en PDF. J'ai installé
ce plugin en utilisant Composer et en suivant les instructions fournies dans le repository GitHub
.

Fig.18 - Installation DOM PDF Composer.

Après avoir installé le plugin, j'ai créé deux fichiers PHP distincts, l'un pour l'étiquette
"defrost" et l'autre pour l'étiquette "expiration". Ces fichiers sont ensuite convertis en un
document PDF qui peut être directement imprimé depuis le browser sur une imprimante
thermique ou autre.
Suivant les instructions de GitHub, le contenu de l'étiquette ainsi que son style, en code
HTML, sont stockés dans une variable $html. Pour le contenu de l'étiquette, j'ai opté pour
un tableau <table> sans bordure qui affiche le nom du produit, la date courante ou la date
à laquelle l'étiquette a été imprimée, la date limite de consommation (DLC) ou la date
maximale de conservation après décongélation, ainsi que le nom de l'employeur ayant
imprimé l'étiquette.
Le plugin nous permet également de configurer la taille de l'étiquette (A7) ainsi que
l'orientation du papier imprimé (paysage pour horizontal).
Lorsque l'utilisateur clique sur l'un des deux boutons disponibles dans la fenêtre pop-up
JavaScript, "defrost" ou "expiration", il est redirigé vers le fichier PDF avec l'option
d'impression située dans le coin supérieur droit.
20

<Fig.19
pdf_defrost.php
script (html et css)

Fig.20 - exemple d'une étiquette defrost | pdf_expiration.php


21

4.3 CRD - Add Delete Product

Cette application dispose d'un catalogue de produits qu'offre la possibilité d'ajouter et de


supprimer des produits alimentaires à tout moment. Cependant, cette fonctionnalité est
réservée exclusivement aux administrateurs. Lorsqu'un administrateur ajoute un produit au
catalogue, celui-ci devient automatiquement visible sur la dashboard (voir chapitre 4.1).
Avant de créer le modèle dédié à cette fonctionnalité, j'ai développé une page de formulaire add
product accessible aux administrateurs depuis leur profil (user profile).
Ce formulaire utilise la méthode POST et comporte cinq champs à remplir : le nom du produit,
une liste <select> pour choisir la catégorie du produit, deux listes <select> offrant différentes
options de durée (durée maximum de conservation en décongélation et durée de conservation
du produit alimentaire), ainsi qu'un champ de type file permettant de télécharger l'image du
produit sur l'application. Enfin, un champ caché de type "hidden" contenant un token de sécurité
CSRF est également inclus dans le script du formulaire.

Fig 21 - Form Add Product (web et responsive) IMAGE A CHANGE ENCORE!!

Avant de procéder à la requête POST du formulaire vers la base de données, les données sont
vérifiées et soumises à des mesures de sécurité dans le contrôleur
(controller/add_product.php).
Tout d'abord, le nom du produit saisi par l'utilisateur est traité avec la fonction PHP trim() pour
supprimer les espaces extra indésirables. Ensuite, une condition vérifie que le nombre de
caractères est limité à 25 caractères maximum. Si la condition n'est pas respectée, un message
d'erreur est affiché.
22

En ce qui concerne l'image téléchargée par l'utilisateur, sa taille est limitée à 1 Mo. Le contrôleur
prend également des mesures de sécurité contre les téléchargements de scripts ou d'autres
fichiers malveillants sur notre serveur. Il utilise la fonction PHP pathinfo($img_name,
PATHINFO_EXTENSION) pour obtenir l'extension du fichier et vérifie si cette extension est
acceptée en se basant sur un tableau array contenant les types d'extensions autorisées (jpg,
jpeg et png, par exemple).
Lorsque la condition est vérifiée, le nom de l'image reçoit une préfixe appelé "IMG-" et le serveur
la déplace vers le dossier 'assets/img_products/' sur notre serveur. Si la condition n'est pas
respectée, un message d'erreur est affiché. Veuillez noter que dans la base de données, seul le
nouveau nom de l'image est enregistré dans la table "products", pas le fichier lui-même.
Si toutes les conditions sont satisfaites, le contrôleur appelle la fonction create_product() de
notre classe ManageProduct($pdo) et toutes les données sont envoyées à la base de données
MySQL.
23

Fig.22 - controller/add_product.php

La classe ManageProduct, qui est issue du modèle product_manager.php, utilise l'extension


PDO et des requêtes paramétrées pour assurer une communication sécurisée entre le serveur et
la base de données. Cette approche permet de prévenir les attaques par injection SQL.
24

Fig.23 - extrait class ManageProduct (model/manage_product.php)

4.4 Login + Sécurité

Le formulaire login est utilisé pour l'inscription d'un utilisateur sur l'interface (index.php). Ce
formulaire de connexion est rigoureusement sécurisé, et pour ce faire, le script met en place
plusieurs protocoles de sécurité.
Le contrôleur login.php commence par effectuer une sanitisation et une authentification du nom
d'utilisateur fourni par l'utilisateur. Pour cela, la condition utilise une requête paramétrée
prepare() pour protéger contre les attaques par injection SQL aprés un fonction php trim().
25

Les deux champs du formulaire sont également soumis à la fonction htmlspecialchars() pour se
protéger contre les failles XSS (Cross-Site Scripting). Ce protocole de sanitization est utilisé
pour empêcher l'injection de code malveillant dans la page HTML, à la fois du côté client et du
côté serveur.

Si la condition est vérifiée, le serveur effectue un fetch de la ligne (row) correspondant à


l'utilisateur concerné dans la table users. Ensuite, il vérifie l'exactitude du mot de passe saisi à
l'aide de la fonction password_verify() de PHP. Les mots de passe de tous les utilisateurs de
cette application sont protégés en utilisant l'encryptage ARGON2i. Cela garantit que les mots de
passe sont cryptés de manière sécurisée et ne sont pas stockés en texte brut dans la base de
données.

Dans cette étape, si la condition est vérifiée, le serveur commence par stocker toutes les
données nécessaires de l'utilisateur dans une variable superglobale PHP appelée $_SESSION.
Cette pratique est importante pour la gestion des sessions et des permissions exclusives en
fonction du rôle de l'utilisateur tout au long de sa navigation dans l'application. Le token de
sécurité CSRF est également vérifié dans notre condition et stocké dans une variable de
session. Ceci permet de renforcer la sécurité de l'application en s'assurant que les requêtes
proviennent bien de l'utilisateur authentifié et évite les attaques de type Cross-Site Request
Forgery (CSRF).
26

Une autre mesure de sécurité implémentée dans ce formulaire d'inscription est la création d'un
cookie de session. Ce cookie contient un token unique appelé PHPSESSID, qui reste stocké
dans le browser de l'utilisateur pendant une durée de vie de 4 heures. Ce cookie est utilisé pour
maintenir la session active entre le navigateur et le serveur. Tous les tokens et cookies associés
sont détruits lorsque l'utilisateur se déconnecte de l'interface, en utilisant la fonction PHP
unset(). Un nouveau token numérique est généré et stocké dans une variable, puis inséré dans la
fonction setcookie() avec une variable représentant la durée de la session (période de temps).

Fig.24 - extrait /controller/login.php


27

5.0 Recherche

5.1 Contexte de la recherche.

Avant la construction de l'application j'avais quelques doutes de comment j'allais projeté la date
de péremption ou la date de decongélation maximale dans l'étiquette du produit. J’ai réalisé une
petite recherche sur la documentation mysql et la documentation php mais aussi sur google et
stackoverflow pour trouver une solution.
La question c'était de trouver une solution à stocker une période de temps de plus de 24 heures
sur la base de données, pouvoir faire le fetch de cette période de temps pour l’après l'ajouter à la
date courante.
PÉRIODE DE TEMPS + DATE COURANTE = DATE FUTURE
Pendant la construction du formulaire add product, je décide de stocker les données en TIME
data type après un débat entre INTEGER, TIME LAPSE ou TIME data types. Pour cette
information je consulté différentes sources comme stackoverflow et la doc mysql. (extrait.1)
Vu que les valeurs data du type TIME sont limitées entre '-838:59:59' et '838:59:59' je trouvé
TIME comme la meilleure solution. Aucun produit du restaurant sera conservé pour plus de 7
semaines. (extrait 2)
Pendant ma recherche. j’ai aussi me renseigne pour la transformation des valeurs TIME data
type dans le format “XX:XX:XX” en période de temps en seconds. Pour après pouvoir ajouter ces
valeurs au jour et l’heure courante avec la fonction php time() et date(). (extrait 3)

5.2 Extrait du site anglophone.

”MySQL storing duration time - datatype?”

“I need to calculate the time a user spends on site. It is the difference between logout time and
login time that gives me something like "Mr X spent 4 hours and 43 minutes online". So to store
the 4 hours and 43 minutes i declared it like this: duration time NOT NULL
Is this valid or a better way to store this? I need to store it in the DB because I have other
calculations I need to use this for + other use cases.” JUD Dec 21, 2010 at 10:55

“I'd definitely go with TIME. I can't think of anybody spending 34 days in a row online. If so, I'm
ready to let this rare case run into an error. UPDATE statements can be easily done using
ADDTIME(). With this you can also add like 30 minutes and 23 seconds without transferring that
28

into seconds. Nothing is hardcoded, you can always do TIME_TO_SEC() – if you really need that
(what I doubt).” Gerald Sep 3, 2016 at 14:14
- via stackoverflow
stackoverflow.com/questions/4498513/mysql-storing-duration-time-datatype

“11.2.3 The TIME Type”

“MySQL retrieves and displays TIME values in 'hh:mm:ss' format (or 'hhh:mm:ss' format for
large hours values). TIME values may range from '-838:59:59' to '838:59:59'. The hours part may
be so large because the TIME type can be used not only to represent a time of day (which must
be less than 24 hours), but also elapsed time or a time interval between two events (which may
be much greater than 24 hours, or even negative).”

- via MYSQL Documentation

dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html

“PHP Converting hours, minutes & seconds string to seconds”

“Converting hours, minutes and seconds (H:i:s) string to just seconds with PHP can be done
with an adaptable function that also works for just a minutes and seconds string.

The time string to seconds function:

(...)

The function works by checking if the string after being split, contains 3 elements which are
hours, minutes and seconds otherwise it is just minutes and seconds.

Then the correct elements get multiplied by their respective seconds, i.e an hour is 3600
seconds and a minute is 60. “ anonymous August 21, 2020

- via Blog Write

write.corbpie.com/php-converting-hours-minutes-seconds-string-to-seconds/

6.0 Veille securite


Lors de la veille sur les vulnérabilités de sécurité, je me suis informé sur les différentes mesures
de protection. Sur discord et avec contact avec des développeurs plus expériencée, j'étais averti
pendant la construction du server à utiliser un protocole de sécurité contre des failles CSRF
(cross site request forgery) vue le manque de frameworks php dans ma tech stack php vanilla.
J’utilisé différents cours sur youtube pour me renseigner du côté pratique.
29

Je me tiens également informé des différentes avancées ou failles potentielles dans les
domaines informatiques au sens large grâce à des sites comme www.krebsonsecurity.com,
reddit et des chaines youtube et des nouvelles plateformes d'intelligence artificielle open source
pour le debug et optimisation des mesures de sécurité.

7.0 Annexes

Fig. 25 - Le premier
prototype zoning et
wireframe.

Fig. 26 - Exemple du
parcours d'une denrée
alimentaire dans la
restauration et les phases
de chaque étiquette.
30

Fig. 27 - User Role Permission Model.

Fig. 28 - Impact
Mapping.

8.0 Remerciements

Transition Pro Grand Est - Financement de la formation DWWM.


Béatrice Lescop, Conseillère Régionale - Aide à la rédaction du dossier Transition Pro.
Mathieu Quittard - Formateur PHP Symfony.
Thibaud Di Domenico - Formateur HTML CSS.
Ahmed Seneina - Formateur JavaScript et Reactjs.
Programming with Mosh - YouTuber et créateur de contenu en développement Web.
FireShip - YouTuber et créateur de contenu en développement Web.
DevelopedByEd - YouTuber et créateur de contenu en développement Web.
Freecodecamp.org - Blog Web Dev.

Vous aimerez peut-être aussi