Séance 5 : Modèles - Entités - ORM
Dernière mise à jour
Dernière mise à jour
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.
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.
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.
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.
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.
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)
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.
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.
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.
Configurer votre base de données (dupliquer le .env
en .env.local
et modifier les informations dans le .env.local
)
Si vous utilisez limage docker du cours, 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 Categorie et ajouter les champs suivants
titre string 150 caractères
ordre int
L'id sera automatiquement ajouté
Créer un nouveau contrôleur nommé "CategorieTestController"
Ajouter une route pour créer un nouvel enregistrement
Créer un objet Categorie et compléter les informations (titre, ordre)
Récupérer la connexion à doctrine ($em = $this->getDoctrine()->getManager()
)
Associer l'instance de Categorie avec l'ORM ($em->persist($categorie))
Enregistrer dans la base de données ($em->flush()
)
Appeler la route et vérifier que cela s'enregistre dans votre base de données
Essayer d'appeler la route plusieurs fois.
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')
; ou findByTitle('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
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é.
Créer une deuxième entité "Article" avec :
titre string 255
texte text
datePublication datetime
auteur string 255
image string 255
Ajoutez des données depuis phpMyAdmin dans la table Article ( 3 articles) ou avec un nouveau contrôler de test
Modifiez votre contrôleur et la page "/articles" pour afficher tous les articles de votre table, par ordre décroissant (plus récent au plus ancien)
Modifiez votre page d'accueil pour afficher le dernier article publié.