· 5 min read

3 Nouveautés de Symfony 7.1

Découvrons ensemble trois nouveautés introduite dans Symfony avec la version 7.1: MapUploadedFile Attribute, IsCsrfTokenValid Attribute et MacAddress Constraint.

Découvrons ensemble trois nouveautés introduite dans Symfony avec la version 7.1: MapUploadedFile Attribute, IsCsrfTokenValid Attribute et MacAddress Constraint.

Introduction

A l’heure ou j’écris cet article (le 12/05/2024), dans un train en direction de Genève pour les DevOpsDays 2024, la version 7.1 de Symfony n’est pas encore sortie en version stable.

Cependant, et comme l’équipe de Symfony le fait sur son blog depuis quelques temps, nous avons dèja quelques infos sur les nouveautés marquante de notre Framework favoris.

Pour découvrir les nouveautés j’ai l’habitude d’utiliser ls version RC (Realease Candidat) ou Beta. C’est en générale suffisament stable pour ce faire un avis.

Un projet pour tester

Pour découvrir rien de mieux que d’expérimenter sois-même, en tous cas c’est la méthode la plus efficace avec moi 😁, donc, création d’un projet Symfony dédié aux nouveautés.

Comme on veux installer la prochaine version (7.1.0-BETA1), nous créons le projet avec la commande suivante :

symfony new test-sf71 --version=next --webapp

MapUploadedFile Attribute

Utilisation “simple”

Découvrons ce nouvel attribut qui va grandement nous simplifier la vie pour la gestion des uploads de fichiers.

Créons un controller dédié :

symfony console make:controller upload

Et modifions notre controller pour utiliser ce nouveau attribut MapUploadedFile.

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapUploadedFile;
use Symfony\Component\Routing\Attribute\Route;

class UploadController extends AbstractController
{
    #[Route('/upload', name: 'app_upload', methods: ['POST'])]
    public function index(
        #[MapUploadedFile] UploadedFile $picture,
    ): Response
    {
        dd($picture->getClientOriginalName());
    }
}

Et utilisons le (ici, avec le client API Bruno) :

Bingo, on peut dèja récupérer notre fichier sans rien faire de plus !

utilisation “avancée” : Ajouter des contraintes

Mais, on peut bien évidement aller plus loins, un spécifiant des règles plus précises, par exemple en vérifiant les mimes type :

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapUploadedFile;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Validator\Constraints as Assert;

class UploadController extends AbstractController
{
    #[Route('/upload', name: 'app_upload', methods: ['POST'])]
    public function index(
        #[MapUploadedFile(
            new Assert\File(
                mimeTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
            ),
        )] UploadedFile $picture,
    ): Response
    {
        dd($picture->getClientOriginalName());
    }
}

IsCsrfTokenValid Attribute

Il existe dans Symfony, et depuis longtemps, un moyen de vérifier la validité d’un token CSRF, un élément de sécurité indispensable pour protéger nos formulaires.

Mais, avec la version 7.1, on peut désormais utiliser un attribut pour vérifier la validité du token CSRF hyper simplement.

Créons un controller dédié :

symfony console make:controller csrf

Et modifions notre controller pour créer deux routes, une avec un “formulaires” et une autre pour le traitement (celle qui va vérifier le token CSRF). Nous ajoutons l’attribut IsCsrfTokenValid sur la méthode submit pour vérifier la validité du token CSRF.

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsCsrfTokenValid;

class CsrfController extends AbstractController
{
    #[Route('/csrf', name: 'app_csrf')]
    public function index(): Response
    {
        return $this->render('csrf/index.html.twig', [
            'controller_name' => 'CsrfController',
        ]);
    }

    #[IsCsrfTokenValid('submit')]
    #[Route('/csrf/submit', name: 'app_csrf_submit')]
    public function submit(): Response
    {
        dd('CSRF token is valid');
    }
}

Le petit bout de Twig pour le formulaire :

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

{% block title %}Hello CsrfController!{% endblock %}

{% block body %}

    <form action="{{ path('app_csrf_submit') }}" method="POST">
        <input type="hidden" name="_token" value="{{ csrf_token('submit') }}">
        <button type="submit">Voir la page suivante</button>
    </form>

{% endblock %}

Si on soumet le formulaire sans le token CSRF, on obtient une erreur 401 InvalidCsrfTokenException, et si on soumet le formulaire avec le token CSRF, on obtient le message CSRF token is valid.

Simple, efficace, et surtout, plus lisible !

MacAddress Constraint

Symfony propose dèja de nombreuses contraintes pour valider les données de nos formulaires, et avec la version 7.1, une nouvelle contrainte fait son apparition : MacAddress.

Une adresse MAC (Media Access Control) est un identifiant unique attribué à une carte réseau pour les communications sur le réseau. C’est un identifiant physique. Trés utilisé dans les réseaux informatiques. Traditionnellement, une adresse MAC est codée sur 48 bits (6 octets) et est représentée sous forme hexadécimale.

Créons tout d’abord un DTO pour notre formulaire :

<?php

namespace App\Dto;

use Symfony\Component\Validator\Constraints as Assert;

class MacAddress
{
    #[Assert\MacAddress]
    public $macAddress;
}

Créons un nouveau formulaire pour tester cette contrainte :

symfony console make:form MacAddress

Et modifions notre formulaire pour qu’il utilise notre DTO :

<?php

namespace App\Form;

use App\Dto\MacAddress;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MacAddressType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('macAddress', null, [
                'label' => 'MAC Address',
            ])
            ->add('submit', SubmitType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => MacAddress::class,
        ]);
    }
}

Et enfin, créons un controller pour afficher le formulaire :

symfony console make:controller MacAddress

Modifions notre controller de la manière suivante :

<?php

namespace App\Controller;

use App\Form\MacAddressType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

class MacAddressController extends AbstractController
{
    #[Route('/mac-address', name: 'app_mac_address')]
    public function index(Request $request)
    {
        $form = $this->createForm(MacAddressType::class);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            dd('Valid MAC Address');
        }

        return $this->render('mac_address/index.html.twig', [
            'form' => $form->createView(),
        ]);
    }
}

Et le petit bout de Twig pour afficher le formulaire :

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

{% block title %}Hello MacAddressController!{% endblock %}

{% block body %}

    {{form(form)}}

{% endblock %}

Et voilà, on a un formulaire qui va vérifier si l’adresse MAC est valide ou non :

  • Si l’adresse MAC est valide, on obtient le message Valid MAC Address
  • Si l’adresse MAC n’est pas valide, il ne se passe rien (enfin si, regarder dans vos appels AJAX, vous devriez voir quelque chose 😉

Conclusion

Symfony 7.1 apporte son lot de nouveautés, et ces trois là sont vraiment intéressantes. La gestion des uploads de fichiers est grandement simplifiée, la vérification du token CSRF est plus lisible, et la contrainte MacAddress est une bonne addition pour valider les données de nos formulaires.

Il y a bien évidement d’autres nouveautés, et je vous invite à consulter le blog de Symfony pour en savoir plus.

Back to Blog