1
votes

Les groupes de validation Symfony 4 CollectionType ne fonctionnent pas

J'essaie de valider FormType à l'intérieur de CollectionType avec quelques règles de groupes simples mais cela ne fonctionne pas, mais si j'essaie de faire la même chose sans groupes de validations, cela fonctionne bien. Une idée? Ceci est un exemple complet et simple qui reproduit l'erreur https://github.com/ychakroun / symfony-collection-type-issue

class LinkType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title', TextType::class, [
                'label' => 'Titre du menu:',
                'attr' => [
                    'input-group' => 'true',
                ],
            ])
            ->add('external', ChoiceType::class, [
                'label' => false,
                'expanded' => true,
                'choices' => [
                    'Lien interne' => false,
                    'Lien externe' => true,
                ],
                'choice_attr' => [
                    'class' => 'link-type',
                ],
                'label_attr' => [
                    'class' => 'btn-group btn-group-toggle',
                    'data-toggle' => 'buttons',
                ]
            ])
            ->add('url', UrlType::class, [
                'label' => 'SAISISSEZ L\'URL EXTERNE',
                'attr' => ['placeholder' => 'https://'],
            ])
            ->add('pageVersion', EntityType::class, [
                'required' => false,
                'class' => Page::class,
                'choice_label' => 'name',
            ])
            ->add('category', EntityType::class, [
                'required' => false,
                'class' => Category::class,
                'choice_label' => 'title',
                'query_builder' => function (CategoryRepository $er) {
                    return $er->createQueryBuilder('c')->where('c.enabled = 1');
                },
            ])
            ->add('position', HiddenType::class, [
                'attr' => [
                    'class' => 'my-position',
                ],
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Link::class,
            'cascade_validation' => true,
            'validation_groups' => function (FormInterface $form) {
                /** @var Link $link */
                $link = $form->getData();
                $groups = ['Default'];
                if ($link->getExternal()) {
                    $groups[] = 'isExternal';
                } else {
                    $groups[] = 'isInternal';
                }

                return $groups;
            },
        ]);
    }
}

class StickerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('links', CollectionType::class, [
                'entry_type' => LinkType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'attr' => [
                    'class' => 'collection',
                ],
                'by_reference' => false,
            ])
        ;
    }

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

Et voici les formulaires que j'utilise:

/**
 * Link
 *
 * @ORM\Table(name="link")
 * @ORM\Entity(repositoryClass="App\Repository\LinkRepository")
 */
    class Link
    {

    /**
     * @var mixed
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string|null
     * @Assert\NotBlank()
     *
     * @ORM\Column(name="title", type="string")
     */
    private $title;

    /**
     * @var bool
     *
     * @ORM\Column(name="external", type="boolean")
     */
    private $external;

    /**
     *
     * @var string|null
     *
     * @Assert\NotBlank(groups={"isExternal"})
     * @Assert\Url(groups={"isExternal"})
     * @ORM\Column(name="url", type="text", nullable=true)
     */
    private $url;

    /**
     * @var \App\Entity\PageVersion|null
     *
     * @Assert\NotBlank(groups={"isInternal"})
     * @ORM\ManyToOne(targetEntity="App\Entity\PageVersion")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="page_version_id", referencedColumnName="id", nullable=true)
     * })
     */
    private $pageVersion;

    /**
     * @var \App\Entity\Category|null
     *
     * @Assert\NotBlank(groups={"isInternal"})
     * @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="links")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=true)
     * })
     */
    private $category;

    /**
     * @var \App\Entity\Sticker|null
     *
     * @ORM\ManyToOne(targetEntity="App\Entity\Sticker", inversedBy="links")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="sticker_id", referencedColumnName="id", nullable=true)
     * })
     */
    private $sticker;
}


0 commentaires

3 Réponses :


1
votes

Je pense que vous devez également ajouter les groupes de validation sur l'entité Sticker:

/**
 * Sticker
 *
 * @ORM\Table(name="sticker")
 * @ORM\Entity(repositoryClass="App\Repository\StickerRepository")
 */
class Sticker 
{
    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity="App\Entity\Link", mappedBy="sticker", cascade={"persist", "remove"}, orphanRemoval=true)
     * @ORM\OrderBy({"position"="ASC"})
     * @Assert\Valid(groups={"isInternal", "isExternal"})
     */
    private $links;
}


4 commentaires

Pourquoi ajoutez-vous "Default" dans le groupe? ($ groups = ['Default'];)


Parce que j'ai besoin de valider $ title sans groupes


On dirait que c'est un problème de version de symfony, en 3.4 ça marche :(


Je ne suis pas sûr, si vous le dites, cela signifie que c'est un problème sur Symfony 4



1
votes

Cette option n'est valide que sur le formulaire racine et est utilisée pour spécifier quels groupes seront utilisés par le validateur.

Voici la réponse https://github.com/symfony/symfony/issues/31441


0 commentaires

-1
votes

Bonjour, nous devons ajouter un addEventListener

class StickerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('links', CollectionType::class, [
                'entry_type' => LinkType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'attr' => [
                    'class' => 'collection',
                ],
                'by_reference' => false,
            ])
            ->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmit'));
        ;
        ;
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Sticker::class,
        ]);
    }

    public function onPreSubmit(FormEvent $event)
    {


        if ($event->getData()) {

            $data = $event->getData();
            $data['links'] = array_values($data['links']);
            $event->setData($data);
        }
    }
}


2 commentaires

Lorsque vous répondez à une ancienne question, votre réponse serait beaucoup plus utile aux autres utilisateurs de StackOverflow si vous incluiez un contexte pour expliquer comment votre réponse aide, en particulier pour une question qui a déjà une réponse acceptée. Voir: Comment rédiger une bonne réponse .


cela n'a aucun sens