Symfony 5
Doctrine
Les prérequis
Afin de suivre cette formation assurez vous de bien avoir cloné le projet : PizzaLol
Dans un terminal exécuté les commandes suivante :
# Clone le projet
git clone https://github.com/Djeg/pizza-lol-app.git
# Se rendre dans le repertoire du projet
cd pizza-lol-app
# Aller chercher la branche doctrine/base
git fetch --all
git checkout sf5-doctrine/base
# Install les dépendances et la base de données
sh bin/installLes fixtures
Les fixtures
Toutes applications nécessite un jeux de données préfabriqué afin de pouvoir fonctionner
Doctrine vient avec un composant de fixtures dont le rôle est de créer des données facilement pour le développement
Fixtures signifie "appareillé"
Les fixtures
Installation du composant
# Install les librairies nescessaire à l'utilisation de fixtures
composer require --dev orm-fixturesOuvrez un terminal et saisissez la commande :
Les fixtures
Le composant met à disposition la possibilité de créer des class de "Fixture"
Ces classes hérite de Doctrine\Bundle\FixturesBundle\Fixture
Elle possède une méthode "load" qui reçois une instance de Doctrine\Persistence\ObjectManager
Cet "ObjectManager" se comporte comme l'EntityManager de Doctrine
Ces classes sont situé dans le répertoire src/DataFixtures
Les fixtures
exemple de Fixture :
namespace App\DataFixtures;
use App\Entity\Pizza;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
class PizzaFixtures extends Fixture
{
public function load(ObjectManager $manager)
{
// Création d'une pizza
$pizza = new Pizza();
$pizza->setName('Régina');
$pizza->setPrice(9.90);
// On persist la pizza dans le registre
// de doctrine
$manager->persist($pizza);
// On éxécute les requètes d'enregistrement
// dans la base de données
$manager->flush();
}
}Les fixtures
Afin de créer et d'insérer des fixtures dans notre base de données nous pouvons utiliser la ligne de commande symfony depuis un terminal :
# Créer une nouvelle class de fixtures
symfony console make:fixtures
# Insére les fixtures dans notre base de données
# ATTENTION: Cette commande efface l'intégralité de
# notre base de données
symfony console doctrine:fixtures:loadLes fixtures
Exercice :
- Créer une class de fixture "PizzaFixtures"
- Insérer 3 pizzas dans la base de données
Les fixtures
Correction :
<?php
namespace App\DataFixtures;
use App\Entity\Pizza;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Bundle\FixturesBundle\Fixture;
class PizzaFixtures extends Fixture
{
public function load(ObjectManager $manager)
{
$regina = new Pizza();
$regina->setName('Régina');
$regina->setPrice(9.7);
$vegan = new Pizza();
$vegan->setName('Végétarienne');
$vegan->setPrice(10.5);
$napolitan = new Pizza();
$napolitan->setName('Napolitaine');
$napolitan->setPrice(11.5);
$manager->persist($regina);
$manager->persist($vegan);
$manager->persist($napolitan);
$manager->flush();
}
}
Les relations
Les relations
Dans une base de données les relations sont le fait de lier une ou plusieurs tables entre elles
Doctrine utilise le même concept mais remplace les "table" par des entities
Il éxiste 3 grands types de relations
Les relations « ManyToMany »
Les relations « OneToMany » ou « ManyToOne »
Les relations « OneToOne »
Les relations
Les relations « ManyToMany » associe plusieurs entités avec plusieurs entités
Par exemple, prenons notre pizzeria
On peut dire qu'une pizza possède plusieurs ingrédients
Et dans le sens inverse aussi, un ingrédient est contenues dans plusieurs pizzas !
Les relations
Les relations « OneToMany » ou « ManyToOne » associe une entité avec plusieurs entités ou plusieurs entitès à une seul entité
Prenons l'exemple de notre pizzeria
Un utilisateur peut passer plusieurs commandes
Cependant une commande est associé à seulement un seul utilisateur !
Les relations
Afin de définir un relation, Doctrine utilise des annotations
Nous pouvons écrire les annotations à la main
Ou bien demander à la console symfony de les remplir pour nous avec la commande "make:entity" !
Les relations
Voici un éxemple d'annotation ManyToMany
namespace App\Entity;
use App\Repository\PizzaRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=PizzaRepository::class)
*/
class Pizza
{
/**
* @ORM\ManyToMany(targetEntity=Ingredient::class, mappedBy="pizzas")
*/
private ArrayCollection $ingredients;
public function getIngredients(): ArrayCollection
{
return $this->ingredients;
}
public function setIngredients(ArrayCollection $collection): self
{
$this->ingredients = $collection;
return $this;
}
public function addIngredient(Ingredient $ingredient): self
{
$this->ingredients->add($ingredient);
return $this;
}
public function removeIngredient(Ingredient $ingredient): self
{
$this->ingredients->removeElement($ingredient);
return $this;
}
}Les relations
Voici un éxemple d'annotation ManyToMany
namespace App\Entity;
use App\Repository\IngredientRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=IngredientRepository::class)
*/
class Ingredient
{
/**
* @ORM\ManyToMany(targetEntity=Pizza::class, inversedBy="ingredients")
*/
private ArrayCollection $pizzas;
public function getPizzas(): ArrayCollection
{
return $this->pizzas;
}
public function setPizzas(ArrayCollection $collection): self
{
$this->pizzas = $collection;
return $this;
}
public function addPizza(Pizza $pizza): self
{
$this->pizzas->add($pizza);
return $this;
}
public function removePizza(Pizza $pizza): self
{
$this->pizzas->removeElement($pizza);
return $this;
}
}Les relations
Pour utiliser une relation rien de plus simple !
public function listIngredients(Pizza $pizza): void
{
// Retourne tout les ingredients contenue dans une
// pizza
$ingredients = $pizza->getIngredients();
// Boucle sur les ingredients
foreach ($ingredients as $ingredient) {
echo $ingredient->getName();
}
}Les relations
ArrayCollection est un type spécial de Doctrine
Il se comporte comme un Array !
Il permet d'optimiser les requêtes à la base de données
Il utilise les itérateur PHP
Les relations
Nous pouvons facilement créer des relations en utilisant la console symfony :
# Met à jour notre entité
symfony console make:entity Pizza
# Il suffit alors de spécifier notre relationLes relations
Exercice !
Créer une entité "Ingredient" avec les champs :
- "name" de type string
- "price" de type float
Les relations
Exercice !
Ajouter un un champ de relation à l'entité "Pizza" : "ingredients" en ManyToMany en utilisant la console symfony
Les relations
Exercice !
Créer une classe de fixtures "IngredientFixtures" et créer les ingrédients suivant :
- "Sauce Tomate" : 0.2 €
- "Tomates" : 0.5 €
- "Jambon" : 1 €
- "Olive" : 1 €
- "Chorizo": 1 €
- "Crème fraîche" : 0.4 €
- "Mozzarella" : 0.5 €
- "Gruyère" : 0.5 €
Les références de Fixtures
Lorsque l'on utilise des "Fixtures" nous pouvons définir des références
Ces références nous permettent de conserver une instance d'entité
Nous pouvons dès lors récupérer cette référence depuis un autre fichier de fixtures
Les références de Fixtures
Éxemple de référence dans IngredientFixtures
# Dans IngredientFixtures nous définissons une nouvelle
# référence
$this->setReference('Ingredient:' . $ingredient->getName(), $ingredient);
# Dans PizzaFixtures nous pouvons récupérer la référence :
$ingredient = $this->getReference('Ingredient:Sauce tomate');Les références de Fixtures
Exercice !
- Dans "IngredientFixtures" définiser une référence pour chaque ingrédient
- Dans "PizzaFixtures" ajouter au moins 2 ingredients par Pizza !
Les références de Fixtures
Exercice !
Dans "templates/admin/pizza/list.html.twig" afficher les ingrédients de chaque pizza (sans leurs prix)
Les relations et les formulaires
Il existe un champs de formulaire dédié au relation
Ce champs est "Symfony\Bridge\Doctrine\Form\Type\EntityType"
Il permet à un formulaire de pouvoir attacher une ou plusieurs entités à notre "data_class"
Les relations et les formulaires
Éxemple d'utilisation d'EntityType
// Dans un formulaire, par éxemple "AdminPizzaType"
// nous rajoutons un champs "ingredients" qui doit
// être une séléction d'entités :
$builder
->add('ingredients', EntityType::class, [
// Le class de l'entité que l'on veut attacher
'class' => Ingredient::class,
// La proprité de "Ingredient" qui sera affiché dans
// notre formulaire
'choice_label' => 'name',
// Est-ce que l'on peut séléctionner plusieurs
// entités ?
'multiple' => true,
])
;Les relations et les formulaires
Exercice
Dans "AdminPizzaType" rajouter un champ "ingredients" qui est une sélection d'entités multiple !
Les fixtures Alice
Il existe un bundle Symfony nous permettant de définir des fixtures plus simplement !
Ce "bundle" c'est "hautelook/alice"
Il utilise le format yaml afin de définir simplement des fixtures
Ces fichiers yaml doivent se situé dans le répertoire "fixtures"
Les fixtures Alice
Voici un exemple de fichier yaml alice :
# Nous générons des Pizzas
App\Entity\Pizza:
# Nous donnons un nom à notre pizza
pizza_regina:
name: 'Régina'
price: 9.5
# Nous pouvons générer automatiquement
# plusieurs pizza à la fois !
pizza_automatique_{0..10}:
# Il est aussi possible de générer des mots
# et des nombre aléatoire !
name: '<word()>'
price: '<numberBetween(5, 14)>'
# Nous pouvons aussi définir des relations
ingredients:
- @ingredient_tomate
- @ingredient_saucisse
Les fixtures Alice
Installation d'Alice
# Lancer cette commande afin d'installer alice
composer require --dev hautelook/alice-bundleLes fixtures Alice
Chargement des fixtures
# Lancer cette commande afin de d'insérer les fixtures
# dans la base de données
symfony console hautelook:fixtures:loadLes fixtures Alice
Exercice !
Créer un fichier "fixtures/fixtures.yml"
Reprendre les pizza dans "src/DataFixtures/PizzaFixtures" et "src/DataFixtures/IngredientFixtures" et les rajouter dans le fichier "fixtures/fixtures.yml" en utilisant la syntax "yaml"
Supprimer le repértoire "src/DataFixtures"
Charger les fixtures dans la base de données
Exercice Final !
Pouvoir créer, lister, mettre à jour et supprimer des ingrédients !
Exercice Final !
Exercice 1: Lister les ingrédients
Créer un controller dans le répertoire "src/Controller/Admin" nommé "IngredientController"
Ajouter un méthode "list" avec une route "/admin/ingredients/list"
Récupérer tout les ingrédients de la base de données
Afficher les ingrédients dans un template "admin/ingredient/list.html.twig"
Exercice Final !
Exercice 2: Menu de navigation
Créer un template "admin/_menu.html.twig" avec un menu de navigation
Créer un template "base_admin.html.twig" dans le répertoire "admin"
Hériter de 'base.html.twig' dans "base_admin.html.twig" et inclure le menu
Retoucher tout les templates dans "admin/" et hériter de "base_admin.html.twig"
Exercice Final !
Exercice 3: Créer un ingrédient
Créer un form "AdminIngredientType" avec les champs "name", "price" et "submit"
Créer une méthode dans "IngredientController" nommé create attaché la route "/admin/ingredients/create"
Utiliser le formulaire (si valide, enregistrer l'ingrédient en utilisant doctrine et rediriger sur la liste des ingrédients, sinon afficher le template "admin/ingredient/create.html.twig")
Ajouter un lien dans "list.html.twig" vers la page "create.html.twig"
Exercice Final !
Exercice 4: Supprimer un ingrédient
Créer une méthode "delete" dans le controller "IngredientController" avec la route "/admin/ingredients/{id}/delete"
Supprimer l'ingrédient en utilisant doctrine
Rediriger vers la page "list" des ingrédients
Ajouter un lien dans "list.html.twig" afin de supprimer un ingrédient
Exercice Final !
Exercice 5: Mettre à jour un ingrédient
Créer une méthode "update" dans le controller "IngredientController" avec la route "/admin/ingredients/{id}/update"
Utiliser le formulaire "AdminIngredientType" afin de mettre à jour un ingrédient (si le formulaire est valide, enregistrer l'ingrédient en utilisant doctrine et rediriger vers la liste des ingrédients, sinon afficher le formulaire dans le template "update.html.twig")
Mettre à lien dans "list.html.twig" afin de pouvoir éditer un ingrédient.
Exercice Final !
Exercice 6: Bonus, une liste générique
Créer un template "admin/_list.html.twig" et placé le code qui liste des ingrédients ou des pizzas
Inclure et utiliser ce template dans la liste des ingrédients et des pizzas en utilisant des paramètres d'inclusion
Symfony 5 - Doctrine
By David Jegat
Symfony 5 - Doctrine
- 184