Archives de l’auteur : Numa

Symfony : Conserver les données d’un multi step form après au clic sur un bouton précédent

La version 7.4 de symfony propose un nouveau compposant, le « Multi-Step Forms ».
Pour configurer la navigation dans celui-ci vous devez créer une classe qui gère le fonctionnement des bouton et l’indiquer sur votre formulaire principal

$builder->add('navigator', MySecoursNavigatorType::class);

Par défaut le clic sur le bouton précédent, écrase les valeurs de l’étape en cours, ce qui à pour conséquence que si vous êtes à l’étape 4 et que vous revenez à l’étape 1 en cliquant sur précédent à multiple reprise, tous les données des étapes 2,3 et 4 seront effacés. L’astuce est de modifier la configuration par défaut du bouton précédent en passant « ‘clear_submission’ => false ». Cela aura aussi pour effet de soumettre l’étape courante, vous pouvez éventuellement ajouter l’option « ‘validation_groups’ => false, » si la validation de cette étape ne vous intéresse pas lors du clic sur précédent, elle sera a nouveau faite par la suite lors du clic sur le bouton suivant.

<?php

namespace App\Form\MultiStep;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Flow\FormFlowCursor;
use Symfony\Component\Form\Flow\Type\FinishFlowType;
use Symfony\Component\Form\Flow\Type\NextFlowType;
use Symfony\Component\Form\Flow\Type\PreviousFlowType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MyNavigatorType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('previous', PreviousFlowType::class, [
                'label' => 'Précédent',
                'include_if' => fn (FormFlowCursor $cursor) => !$cursor->isFirstStep(),
                'clear_submission' => false,
                'validation_groups' => false,
            ])
            ->add('next', NextFlowType::class, [
                'label' => 'Suivant',
                'include_if' => fn (FormFlowCursor $cursor) => !$cursor->isLastStep(),
            ])
            ->add('finish', FinishFlowType::class, [
                'label' => 'Valider',
                'include_if' => fn (FormFlowCursor $cursor) => $cursor->isLastStep(),
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'label' => false,
            'mapped' => false,
        ]);
    }
}

Symfony : connaître tous les rôles d’un utilisateur (selon la hiérarchie configuré)

Mise à jour, Mai 2025

Cela deviendra une fonction native à partir de Symfony 7.3 avec isGrantedForUser voir https://symfony.com/blog/new-in-symfony-7-3-arbitrary-user-permission-checks

Dans les version antérieures :

Exemple rapide

namespace App\Security\Voter;

use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;

class UserVoter extends Voter
{

public const EDIT = 'USER_EDIT';

public function __construct(private RoleHierarchyInterface $roleHierarchy) {
}

protected function supports(string $attribute, $subject): bool
{
return \in_array($attribute, [self::EDIT, self::TRANSFER, self::DELETE, self::SEE_NDE]) &amp;&amp; $subject instanceof User;
}

protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
/** @var User $user */
$user = $token-&gt;getUser();
//
$subjectRoles = $this-&gt;roleHierarchy-&gt;getReachableRoleNames($subject-&gt;getRoles());
$userRoles = $this-&gt;roleHierarchy-&gt;getReachableRoleNames($user-&gt;getRoles());
//je ne peux pas modifier un utilisateur ayant plus de rôles que moi
if(count($subjectRoles) &gt; count($userRoles)) {
return false;
}
return true;
}
}

Symfony : Se débarrasser de « sensio/framework-extra-bundle »

Note rapide

remplacer les

use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;

par

use Symfony\Component\Security\Http\Attribute\IsGranted;

et l’utilisation

* @IsGranted("editProject", subject="entity")

par

#[IsGranted('editProject', 'entity')]

remplacer les

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;

par

use Symfony\Bridge\Doctrine\Attribute\MapEntity;

et l’utilisation

/**
* @Entity("project", expr="repository.findDetails(id)")
*/

public function emptyElements(Project $entity)

par

public function emptyElements(
        #[MapEntity(disabled: true, expr: 'repository.findDetails(id)')]
       Project $entity
        )

pour les paramConverter, ce cas peut etre supprimé directement

* @ParamConverter("day", options={"format": "Y-m-d"})

Une fois tous les élements de ce type supprimé/remplacer on peux supprimer le sensio/framework-extra-bundle du fichier composer.json et mettre à jour