Vous êtes sur la page 1sur 41

14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Créer une application web avec Symfony - Doctrine


#doctrine #php #symfony

@alioukahere 550
16 oct. 2021

Hey salut, bienvenue dans cette série de tutoriel sur Symfony. Dans les
précédentes partie nous somme allés jusqu'à créer les relations entre nos
entités. Dans cette partie nous allons voir comment utiliser le gestionnaire
d'entité de Symfony pour ajouter, modifier ou supprimer des objets en base de
données et nous allons aussi utiliser les repositories pour pouvoir lire nos
enregistrements. Alors t'es prêt? On commence tout de suite.

Mais avant, il faut cloner le dépôt du projet pour pouvoir pratiquer avec moi:

$ git clone https://github.com/kaherecode/symfony-ticketing-app.git


$ cd symfony-ticketing-app

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 1/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

$ git checkout entities


$ composer install

Et voilà, c'est partit.

# EntityManager
Le gestionnaire d'entités ( EntityManager ) est un objet Doctrine qui va nous
permettre de Gérer nos entités, nous allons l'utiliser pour ajouter, modifier ou
supprimer des objets en base de données. Pour récupérer l'EntityManager
dans un contrôleur:

Si le contrôleur hérite de la classe


Symfony\Bundle\FrameworkBundle\Controller\AbstractController , on
peut faire $this→getDoctrine()→getManager()
Si le contrôleur n'hérite pas de la classe
Symfony\Bundle\FrameworkBundle\Controller\AbstractController , il faut
ajouter un argument à la fonction comme ceci
createProduct(EntityManagerInterface $entityManager)

Le deuxième point est valable même si le contrôleur hérite de la classe


Symfony\Bundle\FrameworkBundle\Controller\AbstractController .

# Ajouter des objets


Nous allons créer et ajouter un objet Event en base de données, pour cela
nous allons définir une nouvelle route /events/create et nous allons la
mettre dans la classe EventController que nous avons déjà créer.

<?php
<? h
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 2/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
<?php
// src/Controller/EventController.php

namespace App\Controller;

use App\Entity\Event;
use App\Entity\Tag;
use DateInterval;
use DateTime;
use DateTimeImmutable;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class EventController extends AbstractController


{
/**
* @Route("/events/create", name="create_event")
*/

public function createEvent(): Response


{
// on crée un événement, ces données pourraient venir d'un form
$event = new Event();
$event->setPicture('https://images.pexels.com/photos/251225/pex
$event->setTitle('À la découverte du développement web');
$event->setAddress('Sacré Coeur 3 VDN, Dakar');
$event->setDescription('Lorem ipsum dolor sit amet consectetur
adipisicing, elit. Libero tenetur beatae repellendus possim
quae! Impedit soluta sit iusto amet unde repudiandae fugit
perspiciatis, deleniti quod placeat.');
/ la date de l'événement c'est dans 14 jours à 10h30
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 3/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
// la date de l événement c est dans 14 jours à 10h30
$event->setEventDate((new DateTime('+14 days'))->setTime(10, 30
$event->setIsPublished(true); // on publie l'événement
$event->setPublishedAt(new DateTimeImmutable());

// on crée un deuxième événement qui ne sera pas publié pour l'


$event2 = new Event();
// on renseigne seulement le titre qui est obligatoire
$event2->setTitle('Événement à venir, pas encore publique');

// on ajoute quelques tags à l'événement


$webTag = new Tag();
$webTag->setLabel('web');
$event->addTag($webTag);

$codeTag = new Tag();


$codeTag->setLabel('code');
$event->addTag($codeTag);

/* on récupère le gestionnaire d'entités qui va nous permettre


d'enregistrer l'événement */
$entityManager = $this->getDoctrine()->getManager();

/* on confie l'objet $event au gestionnaire d'entités,


l'objet n'est pas encore enregistrer en base de données */
$entityManager->persist($event);

// on confie aussi l'objet $event2 au gestionnaire d'entités


$entityManager->persist($event2);

* on exécute maintenant les 2 requêtes qui vont ajouter


https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 4/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
/* on exécute maintenant les 2 requêtes qui vont ajouter
les objets $event et $event2 en base de données */
$entityManager->flush();

return new Response(


"Les événements {$event->getTitle()} et {$event2->getTitle(
ont bien été enregistrés."
);
}

// ...
}

On crée deux objets $event et $event2 que nous allons ajouter en base de
données par la suite, l'objet $event est disponible publiquement et l'objet
$event2 pas encore. La partie création des objets est plutôt basique. Laisse
moi t'expliquer un peu comment nous utilisons l'EntityManager:

Sur la ligne 54, nous récupérons le gestionnaire d'entités avec


$this→getDoctrine()→getManager() . Dans la dernière section je te disais
que tu peux faire comme cela ou passer le gestionnaire d'entités en
paramètre à la fonction comme ceci
createProduct(EntityManagerInterface $entityManager)
Sur la ligne 58, nous prenons l'objet $event et nous le confions au
gestionnaire d'entités. À partir de là, le gestionnaire d'entités connaît
l'existence de l'objet $event , il va donc l'ajouter à la liste d'objets à gérer.
La fonction persist($event) n'exécute aucune requête encore
Sur la ligne 61, nous faisons la même chose pour l'objet $event2 .
Maintenant le gestionnaire d'entités gère deux objets $event et $event2 .

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 5/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Si tu as d'autres objets, il faudra faire la même chose pour que le


gestionnaire d'entités connaissent leur existences
Sur la ligne 65, la fonction flush() va exécuter les requêtes SQL pour
chaque objet qui se trouve dans la liste des objets à gérer du gestionnaire
d'entités. Dans notre cas, les objets $event et $event2 sont ajoutés en
base de données, et nous, on n'a écrit aucune requête SQL

Avant d'aller tester l'enregistrement de nos objets, nous allons juste un peu
modifier l'entité Event pour mentionner les valeurs par défaut createdAt et
isPublished :

<?php
// src/Entity/Event.php

namespace App\Entity;

use App\Repository\EventRepository;
use DateTime;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity(repositoryClass=EventRepository::class)
*/
class Event
{
// ...

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 6/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

/**
+ * @ORM\Column(type="boolean", options={"default": false})
*/
private $isPublished;

// ...

public function __construct()


{
$this->tags = new ArrayCollection();
+ $this->createdAt = new DateTimeImmutable();
+ $this->isPublished = false;
}

// ...
}

J'en ai aussi profité pour définir le champ isPublished comme false par
défaut en base de données. Il faut donc exécuter les migrations pour le
prendre en compte:

$ symfony console make:migration


$ symfony console doctrine:migrations:migrate

Tu peux maintenant naviguer sur la page https://localhost:8000/events/create


pour enregistrer les données:

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 7/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Oouuppsss! On a une erreur. L'erreur dit qu'il y a des entités qui n'ont pas été
persisté. Nous avons juste persister les objets $event et $event2 , mais
l'objet $event contient deux autres objets $codeTag et $webTag dont nous
n'avons pas persister, le gestionnaire d'entités ne sait donc pas quoi faire de
ces objets, il ne peut pas les enregistrer parce qu'on ne lui a pas dit de le faire,
mais il a besoin des identifiants de ces objets pour faire la relation. Nous
pouvons soit persister les deux objets $codeTag et $webTag et nous ferons
la même chose à chaque fois, même si l'événement à 10 tags, ou nous
pouvons demander à Doctrine de gérer cela automatiquement, il devra
persister les objets et les ajouter en base de données s'ils n'existent pas. Pour
cela, nous allons modifier l'entité Event au niveau de la relation entre Event
et Tag :

<?php
// src/Controller/Event/php

namespace App\Entity;

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 8/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

use App\Repository\EventRepository;
use DateTime;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity(repositoryClass=EventRepository::class)
*/
class Event
{
// ...

/**
+ * @ORM\ManyToMany(
+ * targetEntity=Tag::class,
+ * inversedBy="events",
+ * cascade={"persist"}
+ * )
*/
private $tags;

// ...
}

Nous rajoutons cascade={"persist"} dans l'annotation, quand tu retournes


maintenant sur la page https://localhost:8000/events/create:

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 9/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Pour vraiment être sûr que l'enregistrement a passer, exécute la commande:

$ symfony console doctrine:query:sql 'select title, event_date, created

Et là biimmmm!!!

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 10/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

On a bien les deux événements enregistrer. Dans les prochaines sections,


voyons comment récupérer des données depuis la base de données et les
afficher sur notre page d'accueil.

# Lire des objets depuis la BDD


Pour lire des objets depuis la base de données, nous allons utiliser ce qu'on
appelle un repository . Un repository c'est une classe PHP qui va nous
permettre de récupérer les objets d'un entité depuis la base données. Lorsque
nous avons généré l'entité Event par exemple, deux classes ont été créés:
Event et EventRepository . C'est le cas pour toutes les entités.

Regardons ensemble le contenu du fichier EventRepository.php dans le


dossier src/Repository/ :

<?php

namespace App\Repository;

use App\Entity\Event;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
* @method Event|null find($id, $lockMode = null, $lockVersion = null)
* @method Event|null findOneBy(array $criteria, array $orderBy = null)
* @method Event[] findAll()
* @method Event[] findBy(array $criteria, array $orderBy = null, $l
*/
class EventRepository extends ServiceEntityRepository
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 11/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

{
public function __construct(ManagerRegistry $registry)

{
parent::__construct($registry, Event::class);
}

// /**
// * @return Event[] Returns an array of Event objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('e')
->andWhere('e.exampleField = :val')
->setParameter('val', $value)
->orderBy('e.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?Event
{
return $this->createQueryBuilder('e')
->andWhere('e.exampleField = :val')
->setParameter('val', $value)
>getQuery()
>g tQ ()
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 12/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
->getQuery()
->getOneOrNullResult()
;

}
*/
}

La classe est plutôt basique, elle hérite d'une classe


ServiceEntityRepository qui vient de Symfony. Dans ce fichier nous allons
définir toutes les méthodes qui vont nous permettre de récupérer des objets
événements depuis la base de données. Le fichier contient déjà deux fonctions
qui sont commentés pour nous montrer un exemple, nous reviendrons sur
ceux-là plus tard.

Si tu regardes sur la Docblock avant la définition de la classe, tu vas voir


quatres méthodes find , findOneBy , findAll et findBy . Ces méthodes
sont prédéfinis par Symfony et sont disponibles pour tous les repositories,
elles sont définies dans une classe EntityRepository qui se trouve dans le
namespace Doctrine\ORM . Généralement ces méthodes suffisent largement,
mais il peut y avoir des cas spéciales ou il faut toi même créer tes propres
méthodes, nous parlerons de cela plus tard, pour l'instant, utilisons les
méthodes de Symfony pour récupérer la liste des événements et les afficher
sur la page d'accueil.

Le contrôleur de la page d'accueil se trouve dans la classe CoreController et


c'est la méthode homepage() . Tu te rappelles de ce qu'on disait lorsque nous
avons parler de l'architecture MVC? Le contrôleur va chercher les modèles
nécessaires puis les envoyer à la vue qui va construire la page HTML et
ensuite le contrôleur frontal retourne cette page. Eh bien, nous avons notre
contrôleur homepage() , la vue core/index.html.twig , il nous manque le

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 13/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

modèle qui est la liste des événements à afficher sur la page d'accueil. Voici le
contrôleur homepage() modifier:

<?php
// src/Controller/CoreController.php

namespace App\Controller;

use App\Repository\EventRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class CoreController extends AbstractController

{
/**
* @Route("/", name="homepage")
*/
public function homepage(EventRepository $eventRepository): Respons
{
$events = $eventRepository->findAll();

return $this->render('core/index.html.twig', ['events' => $even


}

// ...
}

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 14/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Plutôt basique, on injecte la classe EventRepository dans la fonction


homepage() puis nous récupérons tous les événements de la base de
données avec $eventRepository->findAll() , cette fonction retourne un
tableau d'objets événements que nous envoyons ensuite à la vue, nous
pouvons maintenant nous rendre dans la vue parcourir ce tableau et afficher
les événements.

Attention: un autre moyen de récupérer le repository de l'entité dans un


contrôleur, c'est de faire:

/**
* @Route("/", name="homepage")
*/
public function homepage(): Response
{
$eventRepository = $this->getDoctrine()->getRepository(Event::class
$events = $eventRepository->findAll();

return $this->render('core/index.html.twig', ['events' => $events])


}

Personnellement, j'ai une préférence pour l'injection du repository en tant que


paramètre du contrôleur.

Maintenant la vue:

{# templates/core/index.html.twig #}

{% extends 'base.html.twig' %}

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 15/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

{% block title %}Accueil |


{{ parent() }}
{% endblock %}

{% block content %}
<div class="container mt-4">
<div class="row">
<div class="col">
<h2 class="text-center">Événements à venir</h2>
</div>
</div>

<div class="row">
<div class="d-flex flex-row flex-wrap">
{% for event in events %}
<div class="card m-2" style="width: 16rem;">
<img class="card-img-top" src="{{ event.picture
<div class="card-body">
<h5 class="card-title">{{ event.title }}</h
<p class="card-text text-muted">
Le

{{ event.eventDate|date('d/m/Y') }}
<br>
{{ event.address }}
</p>
<a href="{{ path('show_event', {'id': event
</div>
</div>
{% endfor %}
/ i
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 16/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

</div>
</div>
</div>
{% endblock %}

Tout ce qui change c'est de la ligne 19 à 33, nous utilisons la boucle for de
Twig pour parcourir le tableau events qui a été envoyé par le contrôleur puis
à chaque tour, nous avons l'objet courant dans un objet event (sans le s ) et
nous l'affichons. Pour afficher un attribut nous utilisons le point: {{ event.id }}, {{
event.picture }}, et pour afficher la date, il faut la formatter, nous avons utiliser
le filtre date ici, nous allons le modifier dans un instant. Pour l'instant, allons
voir ce que nous avons sur la page d'accueil https://localhost:8000:

Nous avons les 2 événements, le premier s'affiche bien, sans problème. Le


deuxième événement ne devrait pas être là, on est d'accord? Il n'est pas encore
publique. En même temps, dans le contrôleur nous avons utilisé findAll()
pour aller chercher tout les événement de la base de données, mais ça c'était
avant, maintenant voilà ce que le client il veut:

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 17/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Sur la page d'accueil, je veux juste afficher les derniers 12 événements


publiés, afficher du plus proche au plus loin, l'événement de demain va
s'afficher avant celui qui va se passer dans une semaine.

Bon je pense que le client il a vraiment été clair maintenant, qu'est-ce qu'on
fait donc? On crée notre propre méthode? Pas maintenant, nous allons utiliser
une autre méthode fournit par Symfony, on va donc modifier la fonction
homepage() comme ceci:

/**
* @Route("/", name="homepage")
*/
public function homepage(EventRepository $eventRepository): Response
{
$events = $eventRepository->findBy(
['isPublished' => true],
['eventDate' => 'ASC'],
12,
0
);

return $this->render('core/index.html.twig', ['events' => $events])


}

Nous utilisons la méthode findBy() qui prend quatres paramètres:

le premier tableau est celui de la condition, c'est la clause WHERE d'une


requête SQL, dans notre cas nous voulons juste les événements qui ont le
champ isPublished qui est égal à true
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 18/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

le second tableau c'est le ORDER BY d'une requête SQL, nous souhaitons


que les événements soient organisés par date de passage du plus petit
(proche) au plus grand (loin)
le troisième paramètre défini le nombre d'éléments à récupérer, c'est la
clause LIMIT d'une requête SQL, nous voulons juste 12 événements
le dernier paramètre défini l'indice à partir duquel on souhaite lire, c'est la
clause OFFSET d'une requête SQL, nous voulons les 12 derniers
événements, donc on commence à partir de 0

Si tu retournes maintenant sur la page d'accueil:

Bon on ne sait pas si ça a vraiment marcher ou pas, vu que nous avons juste un
événement. Pour pallier à cela, nous allons ajouter au moins quatres
événements publiques. On peut soit lancer MySQL et ajouter nous même ces
données ou utiliser des fixtures.

# Définir des fixtures

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 19/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Les fixtures sont des données de tests que nous ajoutons à notre base de
données. Pour pouvoir les définir, il nous faut installer un nouveau composant
orm-fixtures , avec composer cela va donner:

$ symfony composer require orm-fixtures --dev

On aura besoin de cette dépendance que quand on est en développement.

Une fois l'installation terminer, un nouveau fichier AppFixtures.php sera créé


dans le dossier src/DataFixtures/ , voici le contenu du fichier:

<?php

namespace App\DataFixtures;

use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

class AppFixtures extends Fixture


{
public function load(ObjectManager $manager)
{
// $product = new Product();
// $manager->persist($product);

$manager->flush();
}
}

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 20/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Nous allons définir les objets que nous voulons ajouter dans la base de
données au niveau de la fonction load() , et la dernière ligne de la fonction
$manager->flush() va enregistrer tous les objets que nous aurons persister.

<?php

namespace App\DataFixtures;

use App\Entity\Event;
use App\Entity\Tag;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

class AppFixtures extends Fixture


{
public function load(ObjectManager $manager)
{
$webTag = new Tag();
$webTag->setLabel('web');

$codeTag = new Tag();


$codeTag->setLabel('code');

$apiTag = new Tag();


$apiTag->setLabel('api');

$designTag = new Tag();


$designTag->setLabel('api');

$ 1 E ()
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 21/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
$event1 = new Event();
$event1->setPicture('https://images.pexels.com/photos/251225/pe
$event1->setTitle('À la découverte du développement web');
$event1->setAddress('Sacré Coeur 3 VDN, Dakar');
$event1->setDescription('Lorem ipsum dolor sit amet consectetur
adipisicing, elit. Libero tenetur beatae repellendus possim
quae! Impedit soluta sit iusto amet unde repudiandae fugit
perspiciatis, deleniti quod placeat.');
// la date de l'événement c'est dans 14 jours à 10h30
$event1->setEventDate((new \DateTime('+14 days'))->setTime(10,
$event1->setIsPublished(true);
$event1->setPublishedAt(new \DateTimeImmutable());
$event1->addTag($webTag);
$event1->addTag($codeTag);

$manager->persist($event1);

$event2 = new Event();


$event2->setTitle('API REST - Best Practices');
$event2->setPicture('https://images.pexels.com/photos/3861943/p
$event2->setAddress('Impact Hub Dakar');
$event2->setDescription('Lorem ipsum dolor sit amet consectetur
adipisicing, elit. Libero tenetur beatae repellendus possim
quae! Impedit soluta sit iusto amet unde repudiandae fugit
perspiciatis, deleniti quod placeat.');
// la date de l'événement c'est dans 10 jours à 10h00
$event2->setEventDate((new \DateTime('+10 days'))->setTime(10,
$event2->setIsPublished(true);
$event2->setPublishedAt(new \DateTimeImmutable());
$event2->addTag($webTag);
$event2->addTag($codeTag);
$ 2 ddT ($ iT
i )
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 22/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
$event2->addTag($apiTag);
$manager->persist($event2);

$event3 = new Event();


$event3->setTitle('Introduction au UX/UI Design');
$event3->setPicture('https://images.pexels.com/photos/196644/pe
$event3->setAddress('Toogueda - Lambanyi, Conakry');
$event3->setDescription('Lorem ipsum dolor sit amet consectetur
adipisicing, elit. Libero tenetur beatae repellendus possim
quae! Impedit soluta sit iusto amet unde repudiandae fugit
perspiciatis, deleniti quod placeat.');
// la date de l'événement c'est dans 14 jours à 16h00
$event3->setEventDate((new \DateTime('+14 days'))->setTime(16,
$event3->setIsPublished(true);

$event3->setPublishedAt(new \DateTimeImmutable());
$event3->addTag($designTag);
$manager->persist($event3);

$event4 = new Event();


$event4->setTitle('Symfony + API Platform pour vos API REST');
$event4->setPicture('https://images.pexels.com/photos/270348/pe
$event4->setAddress('Jokkolabs Dakar');
$event4->setDescription('Lorem ipsum dolor sit amet consectetur
adipisicing, elit. Libero tenetur beatae repellendus possim
quae! Impedit soluta sit iusto amet unde repudiandae fugit
perspiciatis, deleniti quod placeat.');
// la date de l'événement c'est dans 5 jours à 10h00
$event4->setEventDate((new \DateTime('+5 days'))->setTime(10, 0
$event4->setIsPublished(true);
$event4->setPublishedAt(new \DateTimeImmutable());
$ 4 ddT ($ iT
i )
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 23/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
$event4->addTag($apiTag);
$event4->addTag($webTag);
$manager->persist($event4);

$event5 = new Event();


$event5->setTitle('Événement à venir, pas encore publique');

$manager->flush();
}
}

Nous ajoutons cinq événements dont quatres sont publics, avec différentes
dates et tags.

Nous allons maintenant exécuter les fixtures pour que ces données soient
ajouter dans la base de données, pour cela il faut exécuter la commande:

$ symfony console doctrine:fixtures:load

Quand tu exécutes la commande, la console te notifie que la base de données


sera purger (totalement vider de son contenu), c'est pour cela qu'il ne faut
jamais utiliser cette commande en production. Saisi donc yes puis Entrer .
Tu peux ouvrir ton gestionnaire de base de données et voir les données qui ont

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 24/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

été ajouter, ou tout simplement aller sur la page d'accueil


https://localhost:8000/:

On a bien les quatres événements publiques qui s'affichent du plus proche au


moins proche, exactement ce que le client il veut.

Bon j'avoue que les boutons en escalier ça fait un peu mal aux yeux, mais on
est pas là pour nous battre avec du CSS et quelques pixels et peut être que
l'événement sur l'UI Design va nous aider avec cela.

Revenons plutôt sur la façon d'afficher la date, pour l'instant nous avons un
affichage basique, mais le client veut que la date s'affiche comme ceci: Le 13
sept. 2021 à 10:30 par exemple. Et en tant que développeur, on fait ce que le
client il veut. Twig dispose d'un filtre format_datetime que nous allons utiliser
pour cela, pour l'utiliser, il faut d'abord installer le composant twig/intl-
extra :

$ symfony composer require twig/intl-extra

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 25/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Et aussi modifier l'affichage de la date dans la vue:

{# templates/core/index.html.twig #}

{% extends 'base.html.twig' %}

{% block title %}Accueil |


{{ parent() }}
{% endblock %}

{% block content %}
<div class="container mt-4">
<div class="row">
<div class="col">
<h2 class="text-center">Événements à venir</h2>

</div>
</div>

<div class="row">
<div class="d-flex flex-row flex-wrap">
{% for event in events %}
<div class="card m-2" style="width: 16rem;">
<img class="card-img-top" src="{{ event.picture
<div class="card-body">
<h5 class="card-title">{{ event.title }}</h
<p class="card-text text-muted">
Le
{{ event.eventDate|format_datetime() }}
<br>
{{
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 }} 26/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
{{ event.address }}
</p>
<a href="{{ path('show_event', {'id': event
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}

Je modifie juste la ligne 26 pour utiliser {{


event.eventDate|format_datetime() }} et cela donne:

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 27/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

OK, nous avons la date en anglais et même si on aimerait dans le futur avoir
un public anglais, pour l'instant le client cible un public français. Sur la
documentation, il est dit que nous pouvons définir le local comme ceci:

{{ event.eventDate|format_datetime(locale='fr') }}

Et voilà!!!

Ceci n'est pas la meilleur manière pour traduire les dates, le mieux c'est d'avoir
le formatage en fonction de la langue de notre application et nous reviendrons
sur cela dans un tutoriel spécifique sur l'internationalisation ( i18n ).

Pour l'instant nous avons à peu près ce que nous voulons, il reste à gérer
l'heure, nous ne voulons pas afficher les seconds:

{{ event.eventDate|format_datetime('medium', 'short', locale='fr') }}


https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 28/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Et nous avons exactement ce que nous voulons.

# Affichage d'un objet


Jusque là, notre page d'accueil marche bien et affiche la liste des prochains
événements. Mais quand on clique sur un événement pour l'afficher, nous
n'avons pas les bonnes infos de l'événement qui s'affichent, nous allons donc
remédier à cela.

La fonction show($id) dans la classe EventController est le contrôleur qui


se charge d'afficher un événement, pour l'instant la fonction se présente
comme ceci:

/**
* @Route("/events/{id}", name="show_event", requirements={"id"="\d+"})
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 29/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

*/
public function show($id): Response
{
return $this->render('event/show.html.twig', ['event_id' => $id]);
}

La fonction prend en paramètre l'id de l'événement à afficher, nous devons


donc récupérer l'événement avec l'id $id et l'envoyer à la vue:

/**
* @Route("/events/{id}", name="show_event", requirements={"id"="\d+"})
*/
public function show($id, EventRepository $eventRepository): Response
{
$event = $eventRepository->find($id);

return $this->render('event/show.html.twig', ['event' => $event]);


}

Nous définissons la classe EventRepository comme paramètre de la fonction


et nous cherchons l'événement avec la méthode find() du repository. Cette
méthode sert à récupérer un objet par son id seulement. Nous allons ensuite
modifier la vue pour afficher les bonnes infos de l'événement:

{# templates/event/show.html.twig #}

{% extends 'base.html.twig' %}

{% block title %}
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 30/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
{% block title %}
{{ event.title }}
|
{{ parent() }}
{% endblock %}

{% block content %}
<div class="hero p-4">
<div class="container">
<div class="row">
<div class="col-sm-12 col-lg-6">
<img src="{{ event.picture }}" alt="" class="img-fl
</div>
<div class="col-sm-12 col-lg-6 mt-3">
<h2>{{ event.title }}</h2>
<p class="card-text text-muted">
Le
{{ event.eventDate|format_datetime('medium', 's
<br>
{{ event.address }}
</p>
<p class="lead">
{{ event.description }}

</p>
<a href="#" class="btn btn-primary">Réserver</a>
</div>
</div>
</div>
</div>
{% endblock %}

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 31/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Et voilà, si tu cliques sur un événement maintenant, tu as bien la page de


l'événement avec ces détails.

Mais nous avons un problème que nous n'avons pas gérer, pour l'instant nous
partons du principe que l'utilisateur va juste cliquer sur un événement pour
l'afficher, qu'est-ce qu'il se passe s'il décide de saisir lui même l'URL et qu'il
saisisse un id qui n'existe pas? Disons https://localhost:8000/events/10000
par exemple pour l'événement qui a l'id 10000, eh bien essaie pour voir:

On a une erreur qui dit qu'il est impossible d'accéder à l'attribut title d'une
variable qui est null . Il faut savoir que la méthode find() retourne null
si l'objet n'existe pas et dans notre cas nous prenons cet objet qui est null
puis nous l'envoyons à la vue, ce qui cause cette erreur.

Pour éviter cela, nous allons vérifier que l'objet $event que nous récupérons
de la base de données n'est pas null , si l'objet est nul, on retourne une
erreur 404 pour dire que l'objet n'existe pas, sinon on retourne la page de
détail de l'événement:

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 32/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

/**
* @Route("/events/{id}", name="show_event", requirements={"id"="\d+"})
*/
public function show($id, EventRepository $eventRepository): Response
{
$event = $eventRepository->find($id);

if (!$event) {
throw $this->createNotFoundException(
"L'événement avec l'id = {$id} n'existe pas!"
);
}

return $this->render('event/show.html.twig', ['event' => $event]);


}

Si tu retournes sur la page https://localhost:8000/events/10000 tu dois


maintenant avoir une page d'erreur avec le statut 404 :

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 33/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Bon c'est vrai que cette page ressemble beaucoup à celle que nous avions
avant, mais si tu regardes bien, le statut de la réponse est 404 cette fois-ci et
c'est ce qui compte vraiment pour ce genre d'erreur. Puis quand nous serons
en production tu ne verras plus cette page, mais la page d'erreur que tu auras
créer toi même.

Mais je trouve la fonction un peu verbeuse, laisse moi te présenter une autre
manière de récupérer automatiquement l'événement ou de lever une exception
NotFoundException si l'objet n'existe pas.

# La magie du ParamConverter
Le ParamConverter va nous permettre de rendre la fonction show() moins
verbeuse. Le ParamConverter va se charger d'aller chercher l'objet en base de
données et si l'objet existe, continuer l'exécution du contrôleur, sinon retourner
une erreur 404 et arrêter l'exécution. Et son utilisation est tellement simple:

/**
* @R t ("/ t /{id}" " h t"
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118
i t {"id" "\d "}) 34/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine
* @Route("/events/{id}", name="show_event", requirements={"id"="\d+"})
*/
public function show(Event $event): Response
{
return $this->render('event/show.html.twig', ['event' => $event]);
}

Nous modifions juste le type du paramètre et nous le définissons comme un


objet de l'entité Event vu que nous voulons chercher dans la table event , si
on voulait chercher dans la table tag on aurait utiliser l'entité Tag . Le nom
du paramètre ne veut rien dire et n'a donc aucune signification dans ce cas-ci.
L'autre point à respecter c'est le nom du paramètre de la requête
/events/{id} donc id dans notre cas ici, le ParamConverter va chercher
l'objet en utilisant ce champ, ce sera donc un WHERE id = :valeur , tu peux
par exemple modifier le id pour passer par un autre champ, mais il faudra
que ce champ soit un attribut de l'entité, sinon il faudra toi même spécifier la
relation. Je te propose d'aller lire la documentation pour mieux comprendre la
puissance du ParamConverter .

# Modifier un objet
Maintenant que nous avons quelques objets en base de données, nous allons
voir comment les modifier.

Modifier un objet ressemble beaucoup à la création d'un nouvel objet, la seule


différence dans le cas de la modification c'est que nous n'allons pas persister
l'objet, parce que le gestionnaire d'objets connaît déjà l'existence de l'objet. Je
vais te présenter ici juste un code pour te montrer l'exemple, mais nous
verrons vraiment tout cela en pratique quand nous parlerons des formulaires.
Disons que nous voulons modifier l'objet qui à l'id 1:
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 35/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

<?php // src/Controller/EventController.php

namespace App\Controller;

// ...

class EventController extends AbstractController


{
// ...

/**
* @Route("/events/{id}/update", name="update_event")
*/
public function update(
Event $event,
EntityManagerInterface $entityManager
): Response {

// grâce au ParamConverter, nous avons automatiquement accès à


$event->setTitle("À la découverte du Web 2.0");
$event->setEventDate((new \DateTime('+14 days'))->setTime(15, 3

$entityManager->flush();

return new Response("L'événement à bien été modifier.");


}
}

Nous modifions le titre et la date de l'événement, puis cette fois-ci nous ne


persistons pas l'objet, parce que le gestionnaire d'entités connaît déjà
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 36/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

l'existence de cet objet, il est lui même aller le chercher en base de données.
Nous appelons directement la méthode flush() pour porter les
modifications en base de données.

Si tu pars maintenant sur l'adresse https://localhost:8000/events/1/update,


l'événement avec l'id égal à 1 sera modifier:

# Supprimer un objet
Pour supprimer un objet, il faut aussi utiliser le gestionnaire d'entités avec sa
méthode remove() :

<?php // src/Controller/EventController.php

namespace App\Controller;

// ...

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 37/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

class EventController extends AbstractController


{
// ...

/**
* @Route("/events/{id}/delete", name="delete_event")
*/
public function delete(
Event $event,
EntityManagerInterface $entityManager
): Response {
// grâce au ParamConverter, nous avons automatiquement accès à
$entityManager->remove($event); // on utilise la method remove
$entityManager->flush();

return new Response("L'événement {$event->getId()} à bien été s


}
}

Et voilà, c'est aussi simple que cela. Pour supprimer l'événement avec l'id égal
à 5, il faut aller à l'adresse https://localhost:8000/events/5/delete.

Voilà, nous avons vu comment créer, lire, modifier et supprimer des objets avec
Doctrine. Dans la prochaine section nous allons passer à un niveau un peu
plus supérieur, nous allons parler des formulaire et commencer à créer les
formulaires pour créer des événements. D'ici là, continue de pratiquer ce que
nous avons appris jusque là, si tu as des questions, n'hésite pas à laisser un
commentaire ci-dessous ou à te rendre sur discord pour en discuter. À plus
tard, prends soin de toi!
https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 38/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Partage ce tutoriel

Merci à

Mamadou Aliou Diallo


@alioukahere
Développeur web fullstack avec une passion pour l’entrepreneuriat et les nouvelles
technologies. Fondateur de Kaherecode.

Continue de lire

@alioukahere
2 oct. 2021

Créer une application web avec Symfony - Les entit...


435 15
min.

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 39/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

@alioukahere
25 sept. 2021

Créer une application web avec Symfony - Les vues


486 13
min.

@alioukahere
1 sept. 2021

Créer une application web avec Symfony - Les contr...


780 13
min.

Discussion
Tu dois être connecté pour participer à la discussion.
Me connecter.

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 40/41
14/12/2021 21:06 Créer une application web avec Symfony - Doctrine

Kaherecode
Apprends à programmer avec des tutoriels pratiques écrit pas des développeurs.

Écrire Contact Chat Discord


©
2021
kaherecode.com.
Tous Droits Réservés.
Développé et maintenue par
alioukahere.

https://www.kaherecode.com/tutorial/creer-une-application-web-avec-symfony-doctrine-61586b876c118 41/41

Vous aimerez peut-être aussi