veilletech.fr
1 nov. Feed du jour
#08 SYMFONY Article

Symfony 8.2 : le contrôleur rattrape ses attributs

Une exception reçue en argument est aussi une exception qu'on peut oublier.

Symfony 8.2 permet à un contrôleur de reprendre la main quand un attribut échoue : il suffit d'un argument nullable typé avec l'exception concernée. Cela évite de retirer #[IsSignatureValid] ou #[RateLimit] pour afficher un message utile. Mais le contrôleur s'exécute alors malgré l'échec, et doit tester l'argument lui-même.

1 min de lectureintermédiairevidéo 1:32
Partager
Sommaire3 sections
  1. Ce qui se passe
  2. Comment s'y prendre
  3. Le piège

Ce qui se passe

Quand #[IsSignatureValid] échouait sur un lien expiré, l'utilisateur recevait une réponse d'erreur. Pour afficher un message et rediriger, il fallait retirer l'attribut et refaire le contrôle soi-même.

Symfony 8.2 (contribution de Kevin Bond, #67563) injecte désormais l'exception dans un argument nullable du contrôleur, s'il en déclare un :

Attribut Exception
#[IsCsrfTokenValid] InvalidCsrfTokenException
#[IsSignatureValid] SignedUriException
#[Lock] LockConflictedException
#[RateLimit] RateLimitExceededException

Comment s'y prendre

Le type de l'argument décide de ce que vous traitez : une sous-classe comme ExpiredSignedUriException restreint le cas, un type union en couvre plusieurs. Cet exemple est écrit pour la fiche à partir de la règle annoncée, sans reprendre celui du billet, et n'a pas été exécuté :

PHP
#[IsSignatureValid]
public function confirmer(?ExpiredSignedUriException $expire = null): Response
{
    if ($expire) {
        return $this->redirectToRoute('renvoyer_lien');
    }

    // Lien valide : suite normale.
}

#[RecoverableAttribute] donne le même comportement à vos propres attributs.

Le piège

Le contrôleur s'exécute même si le contrôle a échoué. Sans test de l'argument, l'action part sans protection. C'est pourquoi #[IsGranted] n'en profite pas. Rien de tel n'empêche d'oublier le test pour un jeton CSRF : placez-le en première ligne et couvrez ce chemin par un test.

Source : Symfony, 30 octobre 2026. Source en anglais.