Séance 5 : Modèles - Entités - ORM
Introduction
Dans Symfony la notion de modèle se retrouve sous la forme (entre autre) d'une Entité. Une entité est une classe PHP, qui peut être connectée à une table de votre base de données via l'ORM. Lorsqu'une entité est liée à une table, via l'ORM, il y a en général un fichier "repository" associé. Un repository permet la génération de requêtes simples ou complexes et dont le développeur peut modifier à volonté.
Un ORM (Object Relation Mapper) permet de gérer manipuler et de récupérer des tables de données de la même façon qu'un objet quelconque, donc en gardant le langage PHP. Plus besoin de requête MySQL, PostgresSQL ou autre.
Symfony utilise Doctrine comme ORM dans son système par défaut. Nous allons utiliser Doctrine mais vous pouvez utiliser d'autres systèmes si vous le souhaitez. Doctrine peut-être géré de plusieurs façon : XML, JSON, YAML, PHP et en Annotation nous allons utiliser ce dernier format de données.
La documentation officielle de Symfony sur l'ORM Doctrine La document officielle de Doctrine
Vous êtes libre d'écrire le code qui permet le traitement métiers en dehors des entités et d'avoir votre propre logique d'organisation.
Mise en application
Configuration
Comme à chaque fois, il est d'abord nécessaire d'installer les bundles nécessaires pour manipuler la base de données avec un ORM. Il vous faut donc exécuter la commande ci_dessous :
On va également installer, si vous ne l'avez pas encore fait, le bundle "maker" qui contient des outils pour générer du code sous Symfony grâce à la console.
Une fois ces deux éléments installés, il faut configurer la connexion à la base de données. Pour ce faire, il faut éditer le fichier .env
à la racine de votre projet, qui doit normalement contenir une ligne d'exemple.
Création de la base de données
Une fois le fichier à jour avec vos données, vous pouvez créer votre base de données depuis la console.
Les modifications de structure de votre base de données devront être réalisées avec la console pour que Symfony puisse faire le lien entre les tables et l'ORM.
Création d'une entité liée à une table
Utilisez la commande make:entity
(qui est dans le bundle maker) pour avoir une série de question vous permettant de créer votre entité avec l'utilisation de l'ORM Doctrine. Vous pouvez créer une nouvelle entité ou modifier (ajouter des champs) une entité déjà existante en saisissant son nom.
Vous allez devoir répondre à une suite de question avec le nom de l'entité (par défaut cela donnera le nom de la table), et les champs à créer. Dans Symfony une entité possède toujours un champs id, qui est la clé primaire et qui est auto-incrémenté. Vous ne devez donc pas l'ajouter dans la console.
Pour la création d'un champs, il vous faudra donner :
son type
sa taille le cas échéant
si ce champs peut être null
s'il doit être unique (index)
Vous pouvez obtenir la liste des types supportés en tapant "?" à la question du type.
Une fois terminé, le fichier d'Entité et le repository associé sont générés.
Exemple dans la console :
Et le code de l'entité généré dans src/Entity/Product.php
:
A ce stade l'entité est créé, mais n'existe pas dans la base de données. Il reste deux étapes à exécuter.
Mettre à jour votre base de données : méthode 1
Sans générer de fichier de migration (qui contient toutes les instructions SQL à exécuter sur la base de données, notamment pour le déploiement d'une mise à jour)
Mettre à jour votre base de données : méthode 2
La création d'un fichier de migration qui va contenir le code SQL a exécuter en fonction de votre SGBD.
La mise à jour de votre base de données en fonction du fichier précédemment généré.
Si vous consultez votre PHPMyAdmin vous verrez la table apparaître.
Modifications de champs et lien base de données
Pour modifier des champs vous pouvez éditer directement le code généré dans la partie annotation: nom (par défaut le nom de la variable), taille, type.
Pour ajouter des champs il vous faut relancer la commande make:entity
en remettant le nom de votre entité.
Après chaque modification ou ajout il faut de nouveau générer le fichier de migration et mettre à jour la base de données. Vous pouvez bien sûr modifier ou créer plusieurs entités avant de faire une mise à jour de votre base de données.
ORM
Une fois la base de données mise en place on va pouvoir insérer, modifier, supprimer et récupérer des informations de la base de données sans saisir de requêtes via des méthodes en initialisant l'entité fraichement créée :
Il existe à la place de $em->persist, $em->remove($post);
qui permettra de faire une suppression.
Exercice
Configurer votre base de données (dupliquer le
.env
en.env.local
et modifier les informations dans le.env.local
)
Si vous utilisez l'image docker MMI, la ligne devrait être
Créer la base de données (
bin/console doctrine:database:create
)Créer une entité (
bin/console make:entity
), nommée Post et ajoute les champs suivantstitre, string de 150 caractères
message, text
datePublication, DateTime
L'id sera automatiquement ajouté
Créer un nouveau contrôleur nommé "Post"
Ajouter une route pour créer un nouvel enregistrement
Créer un objet Post et compléter les informations (titre, message, datePublication)
Récupérer la connexion à doctrine (
EntityManagerInterface $entityManager
) (ne pas oublier le use associé)Associer l'instance de Post avec l'ORM (
$entityManager->persist($post))
Enregistrer dans la base de données (
$entityManager->flush()
)
Appeler la route et vérifier que cela s'enregistre dans votre base de données
Essayer d'appeler la route plusieurs fois.
Recherche d'entité
Symfony et Doctrine proposes des requêtes prédéfinies, qui répondent aux usages les plus courant.
Si $em
est le manager associé à une entité :
$em->find($id);
on récupère qu'un seul élément de l'entité avec l'id$id
;$em->findAll();
on récupère toutes les entrées de l'entité concernée$em->findBy($where, $order, $limit, $offset);
on recherche avec le tableau$where
on tri avec le tableau$order
on récupère$limit
éléments à partir de l'élément$offset
.$em->findOneBy($where, $order);
on récupère le premier élément respectant le tableau$where
et trié avec le tableau$order
;$em->findByX($search);
requêtes magiques où X correspond à n'importe quel champs défini dans votre entité$em->findOneByX($search)
; requêtes magiques où X correspond à n'importe quel champs défini dans votre entitéPar exemple
findBySlug('home')
; oufindByTitle('Bonjour);
génèrera des requêtes de recherche automatiquement. Pour les requêtes avec plusieurs éléments il faudra faire une itération (foreach) ou lister les différents éléments.
Exemple
Si aucune requête prédéfinie ne correspond à vos besoin, vous pouvez bien sûr en créer une en passant par le repository.
Vous pouvez également générer vos requêtes manuellement pour avoir une requête complexe et précise directement dans le controller mais idéalement il faudrait le placer dans le repository dédié.
Et l'utiliser dans votre controller
Modification
Ce dernier code effectue une création dans la base de données; pour une modification il suffit de modifier l'instanciation de l'entité de la sorte :
ici on récupère le repository de Post et on récupère l'id 1 ; tout le restant du code reste inchangé.
Exercice
Créer une entité "PostCategory" avec :
title string 255
Créer une page qui va sauvegarder une catégorie avec le nom "Catégorie 1".
Créer une page qui va sauvegarder un post avec le nom Post 1 à la date courante avec comme message Lorem ipsum.
Créer une page qui va afficher le titre de la catégorie en id 1 et le post en id 1.
Créer un nouveau post identique au premier en changeant le titre.
Créer une page qui affiche la totalité des entités Post.
Créer une page qui récupère le Post avec le Titre "Post 1"
Dernière mise à jour