Symfony检查是否在CollectionType的表单验证中两个字段中的至少一个不为空

问题描述 投票:0回答:1

[在上一个问题(Symfony Check if at least one of two fields isn't empty on form validation)中,我曾向帮助寻求使用回调的表单验证的帮助。 @hous给出的答案是正确的,但不适用于CollectionType中的元素,这是我要打开一个新问题的原因。

基于上一个答案,我已经做了以下工作:

这是我的“母亲”表格:

class BookingVisitorType extends AbstractType
{
    private $router;
    private $translator;

    public function __construct()
    {
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('visitors', CollectionType::class, [
                'entry_type' => VisitorType::class,
                'label' => 'entity.booking.visitors',
                'allow_add' => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'by_reference' => false,
                'entry_options' => [
                    'label' => false,
                    'delete-url' => $options['visitor-delete-url']
                ],
                'constraints' =>[
                    new Count([
                        'min' => 1,
                        'minMessage' => 'validator.visitor.at-least-one-visitor',
                        'max' => $options['numberOfPlaces'],
                        'maxMessage' => 'validator.visitor.cannot-have-more-visitor-than-spaces',
                        'exactMessage' => 'validator.visitor.exact-message'
                    ])
                ]
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Booking::class,
            'numberOfPlaces' => 1,
            'visitor-delete-url' => ''
        ]);
    }
}

这是我的“儿子”表格:

class VisitorType extends AbstractType
{
    private $phone;

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName', TextType::class, [
                'label' => 'entity.visitor.first-name',
                'constraints' => [
                    new NotBlank(),
                    new Length([
                        'min' => 2,
                        'max' => 255
                    ]),
                    new Regex([
                        'pattern' => "/[\pL\s\-]*/",
                        'message' => 'validator.visitor.not-valide-first-name'
                    ])
                ]
            ])
            ->add('phone', TextType::class, [
                'label' => 'entity.visitor.phone-number',
                'required' => false,
                'constraints' => [
                    new Regex([
                        'pattern' => "/[0-9\s\.\+]*/",
                        'message' => 'validator.visitor.not-valide-phone-number'
                    ]),
                    new Callback(function($phone, ExecutionContextInterface $context){
                        $this->phone = $phone;
                    }),
                ]
            ])
            ->add('email', TextType::class, [
                'label' => 'entity.visitor.email',
                'required' => false,
                'constraints' => [
                    new Email(),
                    new Callback(function($email, ExecutionContextInterface $context){
                        if ($this->phone == null && $email == null) {
                            $context->buildViolation('validator.visitor.email-or-phone-required')->addViolation();
                        }
                    }),
                ]
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Visitor::class,
            'error_bubbling' => false,
            'delete-url' => '',
        ]);
    }
}

我的“预订”(缩短的)课程:

/**
 * @ORM\Entity(repositoryClass="App\Repository\BookingRepository")
 */
class Booking
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Visitor", mappedBy="booking", orphanRemoval=true, cascade={"persist"})
     * @Assert\Valid
     */
    private $visitors;
}

最后是我的“访客”(缩短的)课程:

/**
 * @ORM\Entity(repositoryClass="App\Repository\VisitorRepository")
 */
class Visitor
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=45, nullable=true)
     */
    private $phone;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $email;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Booking", inversedBy="visitors")
     * @ORM\JoinColumn(nullable=false)
     */
    private $booking;

    /**
    * @Assert\Callback
    */
    public function validateAtLeastEmailOrPhone(ExecutionContextInterface $context, $payload)
    {
        if ($this->getPhone() === null && $this->getEmail() === null) {
            $context->buildViolation('validator.visitor.email-or-phone-required-for-all')->addViolation();
        }
    }
}

我已经能够解决此问题,方法是在我的VisitorType表单中添加一个属性,该属性由电话值上的Callback约束定义,然后通过email字段上的Callback约束进行检查,但是看起来并不十分“好的做法”。

如果仅尝试调用回调约束,则会收到以下错误消息:“警告:get_class()期望参数1为对象,给定字符串”

非常感谢您的帮助!

forms constraints symfony4
1个回答
0
投票

代替回调函数,您可以创建自己的Constraint。然后,该支票将可重复使用。

我一直使用它来根据自定义规则检查注册密码。

© www.soinside.com 2019 - 2024. All rights reserved.