Symfony

Symfony est un puissant framework PHP offrant des composants pour gérer les requêtes HTTP. Symfony simplifie le développement d'applications web robustes et flexibles.

Informations

Date de publication :

Date de modification :

Catégories : symfony, php, api, webpack, twig, doctrine, html, css, yaml

Auteur : Photo de profil de l'auteur de la documentation meezyr

Sommaire

Bannière documentation Symfony

Symfony est un framework PHP puissant et flexible utilisé pour le développement d'applications web. Il facilite la création d'applications robustes, modulaires et extensibles en utilisant des composants réutilisables. Cette documentation explore certains des composants clés de Symfony et offre des conseils pour développer des applications web efficaces. Consultez la documentation officielle de Symfony pour plus de détails.

1. Nouveau projet

1.1 Installer le CLI

Avant de démarrer un projet, il faut intaller le CLI de Symfony, il y a 2 méthodes pour cela. La première méthode consiste à installer le CLI, pour cela il faut installer Scoop dans le powershell :

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex

Puis il faut installer le CLI de Symfony :

scoop install symfony-cli

Pour plus d'informations sur Scoop, consultez la documentation.

1.2 Télécharger le CLI

La deuxième méthode consiste à télécharger le CLI pour un projet seulement, pour cela il faut télécharger le dossier symfony-cli_windows_386.zip sur le dépôt GitHub et mettre le fichier symfony.exe à la racine du projet.

1.3 Nouveau projet

Pour démarrer un nouveau projet Symfony, il faut ce placer dans le dossier où l'on souhaite avoir notre projet et créer le projet avec la commande suivante :

composer create-project symfony/skeleton my_project

Un fois cette commande faite, pour les autres commandes il faut ce placer dans le dossier racine du projet :

cd my_project

Pour créer une webapp dans un projet Symfony, il faut utiliser la commande suivante :

composer require webapp

1.4 Démarrer le projet

Pour démarrer le projet Symfony, il faut utiliser la commande suivante :

symfony server:start
// ou
.\symfony server:start

On peut retrouver notre projet à l'URL http://127.0.0.1:8000.

1.5 Vider le cache

Pour vider le cache de Symfony en mode dev, il faut utiliser la commande suivante :

php bin/console cache:clear
//ou
php bin/console c:c

En mode prod, il faut utiliser la même commande mais en étant en root. Dans le fichier .env, il faut avoir cela en prod :

APP_ENV=prod
APP_DEBUG=0

1.6 Créer la base de donnée

Pour créer un base de donnée sur Symfony, il faut d'abord configurer les identifiants dans le fichier .env ou .env.local :

DATABASE_URL="mysql://user:mdp@127.0.0.1:3306/basename?serverVersion=mariadb-10.5.4"

Puis pour intaller la base de donnée, utilisez la commande suivante :

php bin/console doctrine:database:create

1.7 Créer une entité

Pour créer une entité, il faut utiliser la commande suivante :

php bin/console make:entity

On peut dans l'entité permettre à un champs datetime de s'enregistrer à la date du jour et l'heure actuelle :

#[ORM\Column(type: 'datetime_immutable', options: ['default' => 'CURRENT_TIMESTAMP'])]

On peut mettre en place des validation pour les champs d'une entité, consultez la documentation officielle, pour cela :

composer require symfony/validator

Une fois les modifications faites sur une ou des entités, il faut utiliser ces commandes pour appliquer les modifications :

php bin/console make:migration
php bin/console doctrine:migrations:migrate

Pour effectuer une suppresion en cascade des données lié, ajoutez ceci dans l'entité :

#[ORM\JoinColumn(onDelete: 'CASCADE')]

Pour optimiser un projet Symfony (surtout en prod), on peut utiliser des traits ce qui permet de réutiliser des champs dans plusieurs entités. Pour en savoir plus, regarder cette vidéo.

Les DataFixtures permettent d'effectuer des testes avec des données, celui-ci importe de données en BDD via une commande symfony :

php bin/console make:fixtures

1.8 Créer un formulaire

La réalisation de formulaires est facile avec Symfony grâce au FormBuilder, consultez la documentation de officielle. Consultez également la liste de tous les types de champs dans un formulaire Symfony, grâce la documentation. Il faut avant tout utiliser cette commande :

composer require symfony/form

Puis pour créer un formulaire, il faut utiliser cette commande :

php bin/console make:form

Pour supprimer un champs d'un formtype dans un contrôleur, il faut utiliser ceci :

$form->remove('description');

1.9 Créer des utilisateurs

Pour créer une entité pour les utilisateurs dans Symfony c'est très simple, il faut utiliser ces commandes :

composer require symfony/security-bundle
composer require symfonycasts/verify-email-bundle

Puis, pour créer l'entité des utilisateurs, il faut utiliser cette commande :

php bin/console make:user

Pour générer la partie connexion à l'utilisateur, il faut utiliser cette commande :

php bin/console make:auth

Pour générer la partie inscription à l'utilisateur, il faut utiliser cette commande :

php bin/console make:registration-form

Pour générer manuellement un hash de mot de passe, il faut utiliser cette commande :

php bin/console security:hash-password

2. Composants Symfony

2.1 Serializer

Le composant Serializer de Symfony permet de transformer des entités dans un format spécifique (tel que JSON ou YAML) et de désérialiser depuis ces formats vers des entités PHP.

2.2 HttpClient, HttpKernel et HttpFoundation

Ces composants sont utilisés pour gérer les requêtes HTTP entrantes et les réponses HTTP sortantes dans l'application Symfony.

2.3 Bundle

Un bundle dans Symfony permet d'ajouter d'ajouter une fonctionnalité spécifique à l'application. Symfony utilise également le terme package pour décrire ces bundles. Voici quelques exemples de bundles à installer :

composer require maker
composer require symfony/orm-pack
composer require symfony/maker-bundle --dev

2.4 HttpFoundation

Le composant Symfony HttpFoundation permet de remplacer les variables globales par des objets, notamment par Request et Response. L'objet Response permet de créer, modifier et envoyer une réponse HTTP.

2.5 Attributes (Depuis PHP 8)

La fonctionnalité attributes de PHP 8 permet d'annoter les classes, méthodes, fonctions, paramètres, propriétés et constantes de classe.

2.6 Traduction

Pour traduire un message d'erreur, il faut utiliser le composant de traduction dans config/packages/translation.yaml :

composer require symfony/translation
framework:
      default_locale: fr
      translator:
           default_path: '%kernel.project_dir%/translations'
            fallbacks:
                  - en

Pour modifier les traductions des messages d'erreurs, cela ce passe dans le fichier translations/security.fr.yaml :

'Invalid credentials.': 'Vos identifiants sont incorrects'

2.7 RateLimiter

Pour limiter les tentatives de connexion, il faut utiliser le composant RateLimiter, dans config/packages/security.yaml :

composer require symfony/rate-limiter
firewalls:
    #...
    main:
        #...
        login_throttling:
                max_attempts: 3
                interval: '5 minutes'

2.8 Validation des Fichiers

Utilisez le composant Validator pour valider les fichiers téléchargés, tels que la taille et le type de fichier, il faut commencer par installer le composant Validator :

composer require validator

Puis dans le FormBuilder utilisez les contraintes :

'constraints' => [
    new File([
       'maxSize' => '1M',
       'maxSizeMessage' => 'Le fichier {{ name }} fait {{ size }} {{ suffix }} et la limite est {{ limit }} {{ suffix }}.',
       'mimeTypes' => [
           'image/png'
       ],
       'mimeTypesMessage' => 'Le type du fichier ({{ type }}) est invalide. Les types requis sont {{ types }}.',
    ])
]

3. Gestion des Routes et Requêtes HTTP

Voici une route sur Symfony :

#[Route(path: '/blog', name:'blog', methods: ['PUT', 'POST'], schemes: ['https'])]

3.1 Principaux Verbes HTTP

  • GET : Récupérer une ressource à l'URI spécifiée, les requêtes GET doivent uniquement être utilisées pour obtenir des données (page HTML).
  • POST : Envoyer une entité vers l'URI spécifiée, le serveur enregistre les données envoyées dans une base de données.
  • PUT : Remplacer une entité par celle envoyée vers l'URI, on l'utilise pour remplacer complètement une entité enregistrée dans une base de données.
  • PATCH : Modifier partiellement une entité avec les changements envoyés vers l'URI, on l'utilise souvent pour modifier partiellement une entité enregistrée dans une base de données.
  • DELETE : Supprimer la ressource indiquée par l'URI.

3.2 Routes Variables

Pour indiquer qu'une partie d'une route est variable et que c'est un paramètre, utilisez ceci :

#[Route(path: '/blog/{nom-de-parametre<regex>?valeur-par-defaut}', name: 'blog')] // Le code regex est à saisir (\d+ ou [a-zA-Z]+)

3.3 Priorité des Routes

Par défaut, toutes les routes ont une priorité de 0. Il suffit donc d'attribuer une priorité de 1 pour que la route soit prioritaire. Pour attribuer une priorité à une route :

#[Route(path: '/blog', name: 'blog', priority: 1)]

3.4 Redirection de Routes

Définissez l'option host pour que l'hôte soit pris en compte lorsqu'une requête est examinée par le Router :

#[Route(path: '/blog', name: 'blog', host: 'ultrage.meezyr.fr')]

Redirigez certaines routes vers de nouvelles routes en utilisant la configuration du fichier de routage. Notamment si vous modifiez votre architecture de routing mais que certains liens sont déjà utilisés ailleurs, par exemple dans config/routes.yaml :

homepage:
    path: /homepage
    controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController
    defaults:
        route: 'accueil'
        keepQueryParams: true
        title: 'Documentation Symfony'
        permanent: true

3.5 Débogage des Routes

Utilisez la console Symfony pour déboguer les routes en utilisant les commandes suivantes :

symfony console debug:router
symfony console router:match /blog

4. Contrôleurs

Pour créer un contrôleur avec Symfony, il faut utiliser la commande suivante :

php bin/console make:controller nomDuController

Pour en savoir plus sur les contrôleurs, consultez la documentation officielle.

4.1 AbstractController

L'AbstractController possède en effet de nombreuses méthodes et permet de rediriger sur une autre route (redirectToRoute()) ou une autre URL (redirect()), de renvoyer un fichier (file()), d'envoyer un message flash (addFlash()), vérifier que l'accès est autorisé, rendre des vues, créer et rendre des formulaires, vérifier la validité d'un token CSRF, d'envoyer une réponse au format JSON...

4.2 Erreurs

La méthode qui permet de retourner une réponse HTTP avec le code de statut 404 pour Not Found (non trouvé) est :

throw $this->createNotFoundException('Rien à cette adresse');

4.3 Redirections

On peut rediriger vers la page précédente grâce à HTTP REFERER, pour cela utilisez le code :

$referer = $request->server->get('HTTP_REFERER');
return $referer ? $this->redirect($referer) : $this->redirectToRoute('home');

5. Twig

Consultez la documentation officielle de Twig.

5.1 Templates

  • templates/base.html.twig : Défini les éléments communs à toutes les pages et contient le header, le footer, l'élément head avec les styles et les scripts globaux.
  • templates/layout.html.twig : Hérite du template base.html.twig et définit la structure de la plupart des pages (sidebar, conteneur, colonnes...). Il n'est bien sûr pas obligatoire de l'utiliser pour toutes vos pages. Certaines parties de l'application peuvent mettre en place un layout spécifique (par exemple : templates/users/layout.html.twig).
  • templates/_partials/_header.html.twig : Permet de séparer des parties de pages, afin d'être réutiliser à d'autres endroit par exemple. Pour cela il faut utiliser {% include "_partials/_header.html.twig" %} là où on souhaite intégrer le code.

5.2 Variable globale

La variable globale app en Twig contient de multiples propriétés :

  • user : l'utilisateur connecté ou null.
  • request : l'objet Request du composant HttpFoundation.
  • session : la session de l'utilisateur ou null.
  • flash : les messages flash de la session courante ou null.
  • environment : l'environnement actuel (dev, test, prod...).
  • debug : vaut true en mode debug.
  • token : contient le token de sécurité.

5.3 Intégration de Contrôleurs dans les Templates Twig

Pour incorporer des contrôleurs dans les templates Twig, utilisez ceci :

{{ render(controller('App\\Controller\\NewsController::lastNews')) }}

Pour utiliser cette fonctionnalité, il faut modifier le fichier config/packages/framework.yaml et il faut décommenter fragments.

5.4 Rendre un template directement

Pour rendre un template directement depuis une route, il suffit de définir le template à utiliser dans le fichier de configuration config/routes.yaml, comme ceci :

privacy:
    path: /privacy
    controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController
    defaults:
        template: 'static/privacy.html.twig'

5.5 Thèmes préconfigurés

Symfony met à disposition des thèmes préconfigurés pour fonctionner avec les principaux frameworks CSS comme Bootstrap, Tailwind ou Foundation, pour cela modifiez le fichier config/packages/twig.yaml :

twig:
    form_themes: ['bootstrap_5_layout.html.twig']

Si vous souhaitez utiliser un thème spécifique pour l'un de vos formulaires, il suffit de faire, dans le template de votre formulaire :

{% form_theme form 'bootstrap_5_horizontal_layout.html.twig' %}

Pour modifier certaines variables de formulaire dans les thèmes, créez le fichier templates/form-theme.html.twig avec ceci au début :

{% use 'form_div_layout.html.twig' %}

Pour en savoir plus, consultez la documentation ou un exemple.

5.6 Détection des erreurs

Le linting est l'exécution d'un programme qui analyse le code pour détecter d'éventuelles erreurs, utilisez la commande :

symfony console lint:twig

Comme pour le Routing, Symfony propose un utilitaire pour vérifier toute la configuration de Twig et tous vos templates, utilisez la commande :

symfony console debug:twig

5.7 Autres

Pour interprèter du HTML avec Twig, il faut utiliser ceci :

{{ description|raw }}

Pour ajouter une class active à un élément HTML en Twig :

class="{{ app.request.pathinfo == path('home') ? 'active' : '' }}"

6. Services et Dépendances

6.1 Services

Les services dans Symfony sont des classes qui effectuent diverses tâches, comme l'envoi d'un e-mail, la journalisation (log), la manipulation d'une base de données... Afin d'obtenir tous les services disponibles dans le conteneur de service, faites la commande suivante :

symfony console debug:container

Pour voir tous les services disponibles pour l'injection de dépendances, faites la commande :

symfony console debug:autowiring

6.2 Création de services

Un service est simplement une classe qui a des méthodes qui réalisent des actions, on peut donc en créer comme ceci :

<?php
namespace App\Service;
class MonSuperService
{
    public function neFaitRien(): void
    {
    }
}

6.3 Validation de Formulaire

Utilisez ValidatorInterface pour gérer soit même les erreurs de formulaire, sans les renvoyer à Twig pour l'affichage, pour cela utilisez ce code :

use Symfony\Component\Validator\Validator\ValidatorInterface;
public function todo(ValidatorInterface $validator)
{
      $todo = new Todo();
      $errors = $validator->validate($todo);
      if (count($errors) > 0) {
            dump($errors);
        return new Response('Une erreur est survenue'));
      }
}

6.4 Manipulation de fichiers

Le service Filesystem permet de manipuler des fichiers et des dossiers, pour cela utilisez le code suivant :

use Symfony\Component\Filesystem\Filesystem;
function __construct(private Filesystem $fs)
{
}

Pour créer par exemple un fichier de log, utilisez ce code :

$fs->appendToFile('log.txt', 'Hello world' . PHP_EOL);

6.5 Arguments

Il est possible de passer manuellement des arguments aux services pour les configurer, il faut modifier le fichier config/services.yaml :

App\Service\MyLog:
    arguments:
        $logFile: 'logs/logs.txt'

6.6 Changer la locale

Pour modifier la locale par défaut de votre application et afficher les dates en français, modifiez le fichier config/packages/framework.yaml comme ceci :

framework:
      default_locale: fr

7. Sessions, messages flash et Cookies

7.1 Gestion des Sessions

Pour configurer les sessions, cela se trouve dans le fichier config/packages/framework.yaml :

session:
    handler_id: session.handler.native_file
    # Pour une semaine :
    cookie_lifetime: 604800
    gc_maxlifetime: 604800
    sid_bits_per_character: 5
    cookie_secure: true
    cookie_samesite: lax
    storage_factory_id: session.storage.factory.native

Pour stocker et récupérer une valeur dans une session, utilisez ce code :

use Symfony\Component\HttpFoundation\RequestStack;
public function index(RequestStack $requestStack): Response
{
    $session = $requestStack->getSession();
    $session->set('clé', 'valeur');
    $session->get('clé');
}

Pour en savoir plus, consultez la documentation officielle.

7.2 Messages Flash

Utilisez les messages flash, ils sont conçus pour afficher des notifications aux utilisateur :

$this->addFlash( 'type', 'Le message' );

Pour en savoir plus, consultez la documentation officielle.

7.3 Gestion des Cookies

Pour définir des cookies, il suffit d'utiliser le code suivant :

use Symfony\Component\HttpFoundation\Cookie;
$response = $this->render('page1.html.twig', [
    'myform' => $form->createView()
]);
$response->headers->setCookie(Cookie::create('clé', 'valeur'));
//ou
$cookie = Cookie::create('clé',  'valeur')
    ->withExpires(strtotime('Fri, 20-May-2023 15:25:52 GMT'))
    ->withDomain('.example.com')
    ->withSecure(true);
$response->headers->setCookie($cookie);
return $response;

Pour récupérer des cookies, il suffit d'utiliser le code suivant :

$request->cookies->get('clé');

8. Doctrine ORM

Doctrine est un ORM (Object-Relational Mapper) pour les projets PHP. Il est intégré par défaut dans Symfony pour la gestion des bases de données. Pour en savoir plus sur Doctrine, consultez la documentation officielle.

8.1 Persistance des Données

Utilisez le gestionnaire d'entité et les méthodes persist() et flush() pour persister des données. Pour éditer des entités, il suffit d'appeler flush() pour exécuter la requête SQL de modification. Il n'y a pas besoin d'utiliser persist() lors d'une édition car Doctrine suit automatiquement les changements des objets récupérés. Pour supprimer un objet c'est très simple, il faut le récupérer en utilisant le répertoire puis envoyer la requête de suppression avec le gestionnaire d'entité.

8.2 Récupération automatique d'entités

Pour récupérer les entités avec le convertisseur de paramètre automatique Doctrine, il suffit d'utiliser le code suivant :

#[Route('/user/{id}')]
public function show(User $user)
{
}

Pour spécifier quel est le paramètre de route correspondant à la clé primaire, il faut utiliser id :

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
#[Route('/user/{user_id}')]
#[Entity('user', options: ['id' => 'user_id'])]
public function show(User $user)
{
}

Pour spécifier un mapping autre que pour la clé primaire, il faut utiliser l'option mapping :

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
#[Route('/user/{user_email}')]
#[Entity('user', options: ['mapping': ['user_email' => 'email']])]
public function show(User $user)
{
}

8.3 QueryBuilder et DQL

Le QueryBuilder est une API de Doctrine qui permet de construire des requêtes DQL conditionnelles :

$query = $this->createQueryBuilder('t')
          ->where('t.priority > :priority')
          ->setParameter('priority', $priority)
          ->orderBy('t.priority', 'ASC')
          ->getQuery();
return $query->execute();

Le DQL (Doctrine Query Language) est le langage de requête de Doctrine :

$em = $this->getEntityManager();
$query = $em->createQuery('SELECT t FROM App\Entity\Todo t WHERE t.prority > :priority ORDER BY t.prority ASC')
    ->setParameter('prority', $priority);
return $query->getResult();

Pour en savoir plus sur QueryBuilder, consultez la documentation officielle.

9. Sécurité et Gestion des Utilisateurs

9.1 Modifier les Rôles utilisateur

Lorsqu'un utilisateur se connecte, vous pouvez lui attribuer d'autres rôles avec le setter setRoles(). Il est nécessaire que tous les rôles commencent par ROLE_.

9.2 Gestion des Rôles et des Permissions

  • Utilisez les rôles comme ROLE_USER et ROLE_ADMIN.
  • Utilisez denyAccessUnlessGranted() pour vérifier les autorisations.
  • Utilisez #[IsGranted('ROLE_USER')] pour appliquer des autorisations aux méthodes du contrôleur (peut être utiliser sur la class d'un contrôleur).
  • Utilisez IS_AUTHENTICATED_FULLY qui vérifie simplement que l'utilisateur est authentifié.

Si vous ne souhaitez pas rediriger l'utilisateur mais exécuter du code en fonction du rôle de l'utilisateur, il faut utiliser la méthode isGranted() :

if ($this->isGranted('ROLE_ADMIN')) {
    // faire quelque chose
}

Vous devez vérifier que l'utilisateur est authentifié soit dans le contrôleur soit directement dans le template sinon vous aurez une erreur si la variable n'est pas définie :

{% if is_granted('ROLE_USER') %}
    <p>Email : {{ app.user.email }}</p>
{% endif %}

Un utilisateur qui est authentifié par session "normal" (après connexion par mot de passe), aura l'attribut IS_AUTHENTICATED_FULLY jusqu'à expiration de la session. Un utilisateur dont la session est expirée et qui s'authentifie automatiquement avec le cookie REMEMBERME aura l'attribut IS_AUTHENTICATED_REMEMBERED.

9.3 Protection contre les Attaques CSRF

Les attaques Cross-Site Request Forgery (CSRF) sont un type d'attaques où le navigateur d'un utilisateur envoie une requête à un site Web tiers sans son consentement et sans qu'il le sache, pour cela dans le fichier config/packages/framework.yaml décommenter la ligne "csrf_protection : true".

9.4 Voter

Les Voters permettent de mettre en place à un endroit les logiques de permissions des utilisateurs et de les réutiliser dans toutes les parties de vos applications qui en ont besoin. Ils sont appelés à chaque fois que vous utilisez denyAccessUnlessGranted() ou isGranted() dans un contrôleur, ou lorsque vous utilisez la propriété access_control dans le fichier security.yaml :

symfony console make:voter
$this->denyAccessUnlessGranted('BLOG_EDIT', $blog);

Pour en savoir plus, consultez la documentation sur les droits d'accès.

10. Événements et Écouteurs

10.1 EventDispatcher

Le composant EventDispatcher de Symfony est le médiateur du pattern du médiateur, il joue aussi le rôle d'observable dans le pattern de l'observeur. Le pattern du médiateur est le fait qu'un seul objet est communiquant avec les autres objets participants. Les autres objets informent le médiateur de leurs changements et le médiateur va prévenir les autres objets de ces changements. Lorsqu'un événement est émis le Dispatcher va appeler tous les écouteurs qui se sont enregistrés pour l'événement.

10.2 EventListener

EventListener est un écouteur qui est simplement une classe avec des méthodes qui peuvent être exécutées lorsque certains événements surviennent. Dans le fichier config/services.yaml :

App\EventListener\LoginListener:
    tags:
        - { name: kernel.event_listener }

Dans le fichier src/EventListener/LoginListener.php :

<?php
namespace App\EventListener;
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
class LoginListener
{
    function __invoke(LoginSuccessEvent $event)
    {
        $request = $event->getRequest();
        $username = $event->getPassport()->getUser()->getName();
        $request->getSession()->getFlashBag()->add('success', 'Bon retour parmi nous ' . $username);
    }
}

Pour en savoir plus, consultez la documentation officielle.

10.3 EventSuscriber

EventSuscriber permet également d'écouter des événements, on peut en créer grâce à cette commande :

symfony console make:subscriber

Pour en savoir plus, consultez la documentation officielle.

10.4 Événements personnalisés

Pour créer des événements personnalisés, on utilise un événement qui est une classe qui doit étendre la classe native Event, comme dans le fichier src/Event/NewUserEvent.php :

use Symfony\Contracts\EventDispatcher\Event;
class UserRegisteredEvent extends Event
{
      public const NAME = 'user.registered';

    public function __construct(private string $email)
      {
    }

    public function getEmail(): string
      {
        return $this->email;
    }
}

On peut émettre un événement personnalisé grâce à la méthode dispatch() disponible sur l'EventDispatcher :

use Symfony\Component\EventDispatcher\EventDispatcherInterface;
$dispatcher->dispatch(new UserRegisteredEvent($email), UserRegisteredEvent::NAME);

10.5  Lifecycle Events

Lifecycle events sont des événements du cycle de vie permettant d'exécuter du code à des moments clés de la persistance des entités, les événements disponibles sont :

  • prePersist : est émis juste avant que l'entité soit persistée (donc pas lors des mises à jour, uniquement lors de la création).
  • postPersist : est émis juste après que l'entité soit persistée (de même uniquement lors de la création). La clé primaire est disponible à ce moment.
  • preFlush : est émis juste avant de flush l'entité (donc de l'enregistrer dans la base de données).
  • preUpdate : est émis juste avant que l'entité soit mise à jour.
  • postUpdate : est émis juste après que l'entité soit mise à jour.
  • preRemove : est émis juste avant que l'entité soit supprimée.
  • postRemove : est émis juste après que l'entité soit supprimée.
  • postLoad : est émis juste après que l'entité soit chargée dans l'EntityManager.

Exemple de Lifecycle events prepersist :

#[ORM\PrePersist]
public function setCreatedAt(): void
{
    $this->createdAt = new \DateTimeImmutable();
}

10.6 Événements dans un formulaire

Pour utiliser un écouteur d'événements avec le composant Form, utilisez le code suivant :

$builder->add('password')->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();
    if ($data->getName() === 'Jean') {
        $form->add('gender');
    }
});

11. Envoi de Courriels

Utilisez le composant Mailer pour envoyer des courriels à partir de l'application Symfony. Pour en savoir plus, consultez la documentation. Pour installer Mailer sur Symfony, il faut utiliser cette commande :

composer require symfony/mailer

11.1 Configuration du Mailer

Configurez le composant Mailer dans le fichier .env en utilisant un serveur SMTP, par exemple Mailtrap :

MAILER_DSN=smtp://c9fb3db1854506:75b5f25e2191c6@smtp.mailtrap.io:2525?encryption=tls&auth_mode=login

11.2 Envoi de Courriels

Pour envoyer un mail avec Mailer, utilisez le code suivant :

use Symfony\Component\Mime\Email;
$email = new Email();
$email->to('Jean Dupont<jean@gmail.com>')
    ->subject('Bienvenue sur Dyma !')
    ->cc('jp@gmail.com,marie@gmail.com')
    ->text('Bienvenue chez nous, nous sommes très contents de votre arrivée !');
$mailer->send($email);

On peut tester l'envoi de mails en mode dev, via un faux serveur SMTP que propose l'outil Mailtrap.

11.3 From général

On peut déclarer un from général pour Mailer dans le fichier config/packages/mailer.yaml :

framework:
    mailer:
        dsn: '%env(MAILER_DSN)%'
        headers:
            from: Ultrage <ultrage@gmail.com>

11.4 Personnalisation de mails

On peut mettre du style dans les mails grâce à Twig :

composer req twig/extra-bundle twig/cssinliner-extra
$email->htmlTemplate('./email/welcome.html.twig')
    ->context(['username' => 'Jean']);

Utilisez le fichier templates/email/welcome.html.twig pour personnaliser l'affichage d'un mail et le CSS doit être dans le fichier public/css/welcome-email.css :

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    {% apply inline_css(source('@css/welcome-email.css')) %}
        <h1>Bienvenue {{username}}</h1>
        <p>Nous sommes heureux de vous compter parmi nous.</p>
      {% endapply %}
</body>
</html>

Pour que cela fonctionne il faut que le fichier config/packages/twig.yaml soit paramétré comme ceci :

twig:
    default_path: '%kernel.project_dir%/templates'
    paths:
        '%kernel.project_dir%/public/css': css
        '%kernel.project_dir%/public/images': images
when@test:
    twig:
        strict_variables: true

Pour intégrer une image à un mail, utilisez le code suivant :

<img src="{{ email.image('@images/monimage.png') }}" alt="monimage">

Pour en savoir plus, consultez la documentation officielle.

11.5 Pièces jointe

Pour attacher des pièces jointe à un mail, il faut utiliser le code :

use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\File;
$email->addPart(new DataPart(new File('/path/to/documents/terms-of-use.pdf')));

Il faut passer la propriété LOCK_DSN du fichier .env à :

LOCK_DSN=flock

12. JavaScript

12.1 Webpack Encore

Avec Webpack, on peut afficher un fichier JS ou/et CSS pour une page uniquement, pour cela dans le fichier webpack.config.js :

.addEntry('app', './assets/app.js')
.addEntry('panier', './assets/panier.js')
.addEntry('compte', './assets/compte.js')

Dans le template Twig, on peut utiliser le code suivant :

{% extends "base.html.twig" %}
{% block stylesheets %}
    {{ parent() }}
    {{ encore_entry_link_tags('panier') }}
{% endblock %}
{% block javascripts %}
    {{ parent() }}
    {{ encore_entry_script_tags('panier') }}
{% endblock %}

Consultez la documentation officielle de Symfony sur Webpack, sachant que Symfony utilise une version modifié de Webpack nommé Webpack Encore.

12.2 Intégration avec Vue.js

Grâce à Webpack Encore, on peut utiliser Vue.js directement dans Symfony, grâce à la commande suivant :

yarn add vue@next vue-loader@next @vue/compiler-sfc

13. Vérifications

Pour vérifier la configuration de votre système avant de lancer Symfony, utilisez la commande :

symfony check:requirements

14. Bundles & Frameworks

14.1 KnpTime

Le bundle KnpTime permet de transformer une date en un message lisible par un utilisateur. Par exemple, il y a x minutes ou x secondes ou x heures, grâce à ce code :

composer require knplabs/knp-time-bundle
{{ comment.createdAt | ago(locale="fr") }

14.2 API Platform

Le framework API Platform permet de créer des API très performantes avec Symfony, pour intaller API Platform il faut utiliser cette commande :

composer require api

Puis pour transformer une entité Symfony en API, il faut mettre ceci dans le fichier de l'entité :

use ApiPlatform\Metadata\ApiResource;
#[ApiResource]

Pour accéder à l'interface de API Platform, utilisez cette URL http://127.0.0.1:8000/api. Pour plus d'information sur la création d'API avec API Platform, consultez la documentation officielle de Symfony.

On peut accèder aux API de Symfony avec Postman qui permet d'intéragir avec les API, pour cela il faut modifier le fichier config/packages/api_platform.yaml :

patch_formats:
        jsonld:   ['application/ld+json']
        jsonhal:  ['application/hal+json']
        jsonapi:  ['application/vnd.api+json']
        json:     ['application/json']
        xml:      ['application/xml', 'text/xml']
        yaml:     ['application/x-yaml']
        csv:      ['text/csv']
        html:     ['text/html']

On peut voir la liste des opérations disponible sur la documentation de API Platform.

14.3 EasyAdmin

Le bundle EasyAdmin permet la création rapide et automatisé d'un backoffice permettant de gérer les donnée d'un projet.

14.4 Éditeurs de texte

Le bundle CKEditor permet l'édition avancé de texte dans un formulaire.

Le bundle TinyMCE permet également l'édition avancé de texte dans un formulaire.

14.5 StofDoctrineExtensions

Le bundle StofDoctrineExtensions permet la création de slugs dans une entité, pour en savoir plus sur l'utilisation de ce bundle, consultez cette documentation.

14.6 LiipImagine

Le bundle LiipImagine permet de recadrer des images.

14.7 LexikJWTAuthentication

Le bundle LexikJWTAuthentication permet de sécuriser une API grâce à l'utilisation de clés privé et public.