Dans cette partie du TD, nous allons créer la base de données associée à notre application web.
Lecture recommandée: la documentation officielle de Symfony.com sur Doctrine
Nous allons dans un premier temps configurer Symfony pour qu'il accède à la base de données.
Pour cela, éditez le fichier .env
et modifiez la valeur de la variable
DATABASE_URL
. Cette dernière ressemblera à ceci:
DATABASE_URL="mysql://127.0.0.1:3306/database?charset=utf8mb4&serverVersion=5.7&user=pizza&password=pizza"
Ici, il faut éventuellement adapter:
Vous pouvez par exemple vérifier en lançant une commande doctrine comme:
symfony console doctrine:schema:validate
Cette commande sert à vérifier que votre base de données est en accord avec votre application, dans votre cas vous n'avez pas encore décrit de classes mappées avec la base de données mais cela peut vous permettre de tester que la connexion fonctionne.
Nous allons maintenant créer nos entités. Pour cela, nous allons utiliser le maker bundle:
symfony console make:entity
Il vous sera alors demandé de nommer votre entité, appellez là Pizza
,
nous utiliserons ici aussi la configuration par annotations.
Vous pourrez alors saisir les champs de manière interactive, ajouter un champ name
de
type string
, un champ description
de type text
, un champ price
de type
float
.
Regarder attentivement le fichier Entity/Pizza.php
qui aura été généré dans vos sources,
son contenu en terme de code est trivial, mais les annotations décrivent la correspondance
avec la base de données.
Maintenant que nous avons créé une entité, nous allons demander à Doctrine de créer la base de données correspondante, pour cela, utilisez:
$ symfony console doctrine:schema:create
ATTENTION: This operation should not be executed in a production environment.
Creating database schema...
Database schema created successfully!
Rendez-vous dans votre base de données, avec par exemple phpMyAdmin et constatez
que la table Pizza
a été créée.
Nous allons ajouter une entité ingrédient, de la même manière que précédemment, créez
l'entité App:Ingredient
ayant juste un champ name
de type string
.
Une deuxième entité Entity/Ingredient.php
apparaîtra.
Maintenant, nous pouvons demander à Doctrine de mettre à jour la base de données, essayez:
$ php bin/console doctrine:schema:update --dump-sql
CREATE TABLE Ingredient (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
Ici, doctrine nous affiche la requête qui permet de mettre à jour la base pour qu'elle
corresponde à nos entités. Vous pouvez également lui demandez d'exécuter les requêtes nécéssaire avec
--force
:
$ php bin/console doctrine:schema:update --force
Updating database schema...
Database schema updated successfully! "1" queries were executed
Une pizza doit avoir plusieurs ingrédients, et un ingrédient doit pouvoir être dans plusieurs pizzas. Pour mettre en relation ces deux entités, il faudrait normalement créer manuellement une table intéremédiaire. Doctrine va également s'en charger pour nous!
Pour cela, modifiez l'entité pizza à l'aide du maker bundle:
symfony console make:entity
Entrez Pizza
, pour y ajouter l'entrée ingredients
, et saisissez le type ManyToMany
. Ensuite, indiquez que la classe est en relation avec Ingredient
.
Enfin, exécutez à nouveau doctrine:schema:update
, en regardant tout d'abord les modifications
qui seront apportées avec --dump-sql
puis en les exécutant avec --force
.
Nous allons maintenant requêter la base de données.
Nous allons créer des pizzas, pour ne pas parler tout de suite des formulaires, nous écrirons une action qui inserera les pizzas.
Voici un exemple:
<?php
// ...
public function insertPizzasAction() {
$em = $this->getDoctrine()->getManager();
$mozarella = new Ingredient;
$mozarella->setName('Mozarella');
$parmesan = new Ingredient;
$parmesan->setName('Parmesan');
$quatreFromages = new Pizza;
$quatreFromages
->setName('4 fromages')
->setPrice(32.2)
->setDescription('Pour les fans de fromage')
;
$quatreFromages->addIngredient($mozarella);
$quatreFromages->addIngredient($parmesan);
$em->persist($quatreFromages);
$em->persist($mozarella);
$em->persist($parmesan);
$em->flush();
return new Response('Pizzas créées');
}
Remarquez l'utilisation des accesseurs (setName
et setDescription
) qui ont été générés
par Doctrine et que l'on peut appeler à la chaîne.
Executez cette requêtes et allez voir dans la base de données pour vérifier la présence des nouvelles lignes dans les tables.
Nous allons maintenant récupérer les pizzas pour les lister. Vous pourrez par exemple utiliser:
<?php
$pizzas = $em->getRepository(Pizza::class)
->findAll();
Ainsi, vous pourrez passer les pizzas en paramètres à une vue comme dans la partie précédente et en afficher la liste. Voici un exemple de code twig:
<ul>
{% for pizza in pizzas %}
<li>{{ pizza.name }}</li>
{% endfor %}
</ul>
Remarquez ici que pizza.name
fera appel à $pizza->getName()
, Twig est assez intelligent
pour utiliser les accesseurs
Vous pourriez également écrire {{ pizza }}
, moyennant une surcharge de la méthode __toString()
de la classe Pizza
Affichez également entre parenthèse tous les ingrédients d'une pizza. Pour cela, c'est très simple,
vous pouvez accéder à l'entrée ingredients
, qui appellera elle-même la méthode getIngredients()
qui retournera un tableau (un peu spécial car géré par Doctrine) contenant tous les ingrédients.
Utilisez le filtre join de Twig pour cela.
Lancez la commande:
symfony console make:crud
Et demandez à Symfony de générer le CRUD pour l'entité Pizza. Consultez les pages
générés (/pizzas
).