Tutorial Jobeet pour Symfony 4 - Partie 6: Aller plus loin avec le modèle
Notre application Jobeet commence à devenir utilisable. Nous savons maintenant créer des pages, les afficher et naviguer entre elles en utilisant le framework Symfony via les différents composants qui sont à notre disposition. Attardons-nous un peu sur la couche modèle de notre projet.
Cette dernière est actuellement composée de nos entités (les classes qui représentent les données stockées en base). Nous allons dans ce chapitre, travailler sur l’optimisation de notre code, ce qui vous permettra d’en apprendre un peu plus sur le sujet.
Revenons sur nos différents scénarios et plus précisément sur le scénario F1: En tant qu'utilisateur, je vois les dernières offres actives sur la page d'accueil
. Car si vous avez bien suivi ce que nous avons réalisé, la page d’accueil liste actuellement toutes les offres d’emploi aussi bien celles qui sont actives que celles qui ne le sont pas.
Un emploi est considéré actif s’il a été posté il y a moins de 30 jours. Commençons par modifier la requête effectuée dans la méthode JobController::index
:
Pour écrire une requête “complexe”, nous utilisons l’objet
QueryBuilder
fourni par Doctrine et qui permet comme son nom l’indique de créer une requête compréhensible par l’ORM sans devoir écrire de code SQL. L’avantage est que Doctrine adaptera la requête au type de base de données avec lequel il communique (SQLite, MySQL, PostgresSQL, …). L’inconvénient est que cela masque complètement la requête qui est générée.
Notre requête commence à devenir plus complexe et il devient intéressant de l’extraire de notre contrôleur pour que cette dernière puisse être réutilisée sans devoir dupliquer le code. Jusqu’à maintenant, la méthode EntityManager::getRepository
nous permettait d’obtenir un objet générique que Doctrine utilise pour fournir des méthodes de base permettant de faire des requêtes en base de données.
Nous allons maintenant définir une classe de type Repository
. Les objets de types Repository
contiennent des méthodes permettant de récupérer des données en base. Définissons donc une classe JobRepository
, qui comme son nom l’indique, nous permettra de récupérer des données liées aux offres d’emploi.
Une fois notre classe créée, nous allons devoir modifier la configuration du mapping de l’entité Job
pour indiquer à Doctrine la classe que l’ORM devra utiliser pour accéder aux données. Cela se passe dans le fichier config/doctrine/mapping/Job.orm.yml
.
Pour finir, supprimons le code du contrôleur pour utiliser notre nouvelle classe :
Et voilà, nous utilisons maintenant une classe pour la récupération des données de notre offre d’emploi, ce qui permet d’isoler le code dédié à la récupération des données et permet ainsi d’améliorer la maintenabilité de notre projet.
Il est possible de consulter la requête générée par Doctrine en consultant les logs générés par l’application. Par défaut, Symfony crée les logs sur la sortie standard et son donc consultable directement sur le terminal.
Un moyen plus simple d’accéder à ces informations est d’installer le composant symfony/profiler-pack
.
Ce dernier permet la mise en place d’une interface graphique qui affiche un certain nombre d’informations sur votre application. Chaque bundle peut ainsi y afficher des données. Cette interface ajoute une barre permettant d’avoir un résumé des informations disponibles :
Il est également possible d’accéder à un détail des informations récupérées en cliquant sur l’icône du composant concerné :
Pour l’heure, notre code est encore loin d’être parfait. Pour récupérer toutes les offres actives, nous sommes systématiquement obligés de passer en paramètre la date à partir de laquelle les offres sont visibles. Cela revient à dupliquer le calcul de la date et serait source d’erreurs. Pour corriger ce problème, nous allons créer une constante qui nous permettra de masquer ce calcul. Et pour optimiser notre requête, nous allons utiliser le champ expiresAt
afin de stocker la date d’expiration d’une offre plutôt que de devoir la calculer.
Tout comme pour les dates de création et de modification de nos offres d’emploi, nous allons utilisons le gestionnaire d’événement de Doctrine pour mettre à jour la valeur du champ automatiquement. Commençons par ajouter le code nécessaire à notre entité :
N’oublions pas d’ajouter la configuration liée à cette gestion d’événement.
Nous pouvons maintenant mettre à jour notre requête :
N’oubliez pas d’enlever le paramètre dans l’appel de la méthode dans la classe
JobController::index
Le code de notre application est maintenant plus simple et plus maintenable, mais si nous voulons pouvoir tester que tout fonctionne correctement, encore faut-il mettre à jour nos données de test. Car dans les données actuelles, nous avons défini une date d’expiration des offres au 10/10/2012 et nous ne voyons donc maintenant plus aucune offre. Supprimons les dates d’expiration de notre jeu actuel et ajoutons une offre expirée (consultez directement ce fichier pour avoir le code correspondant).
En rechargeant les fixtures au travers de la commande bin/console doctrine:fixtures:load
, l’affichage ne devrait pas avoir changé, mais si vous regardez les données en base, vous constaterez qu’il y a pourtant bien 3 offres d’emploi enregistrées.
Si nous revenons à nos scénarios utilisateurs, nous avons spécifié que les offres devaient être classées par catégories, ce qui n’est actuellement pas le cas. Pour répondre à ce besoin, nous allons créer une classe de type Repository
pour notre entité Category
. Cette dernière nous permettra de lister les catégories existantes avec les offres d’emploi correspondantes.
Commençons par modifier le mapping Doctrine :
Créons maintenant la classe correspondante avec la nouvelle méthode de récupération des offres par catégorie :
La requête Doctrine a été construite via le
QueryBuilder
. Doctrine implémente également son propre langage de requête appelé DQL (dérivé du SQL). LeQueryBuilder
tout comme leDQL
se base sur nos entités pour construire les requêtes effectuées en base de données, cela permet ensuite à Doctrine de créer les objets correspondants.
Utilisons maintenant cette dernière dans l’affichage de notre homepage :
Ajoutons la méthode permettant de récupérer les offres actives d’une catégorie :
Modifions ensuite le template en conséquence :
Pour finir, nous allons sécuriser la page de consultation des offres. Effectivement, si vous connaissez l’URL d’une offre, il est possible d’accéder à cette dernière, et ce, même si la date d’expiration est dépassée. Pour cela, rajouter un contrôle dans notre action d’affichage :
Retrouvez tous les tutorials Jobeet disponibles depuis le billet d’introduction de la série. Le code source de cette application est également disponible sur Github. Vous trouvez une branche associée à l’état du projet après chaque chapitre.