【问题标题】:Symfony Check if at least one of two fields isn't empty on form validationSymfony 检查表单验证时两个字段中的至少一个是否不为空
【发布时间】:2020-03-17 10:41:25
【问题描述】:

我已经在脑海中扭转了很长一段时间,但仍然无法找到解决问题的方法。使用 Symfony 4 表单和约束,我无法设置检查以说明在提交包含子表单的表单时,两个字段中的至少一个不能为空。

我有一个 Booking 实体,其中包含一个具有 phoneNumber 属性和 email 属性的 Visitor 实体。我希望能够创建一个具有“访问者”CollectionType 的 Booking(允许我从 BookingType 表单添加访问者)。

我的 BookingType 表单(有点简化):

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

    public function __construct(UrlGeneratorInterface $router, TranslatorInterface $translator)
    {
        $this->router = $router;
        $this->translator = $translator;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('bookableTimeSlot', EntityType::class, [
                'label' => 'entity.booking.bookable-time-slot',
                'class' => BookableTimeSlot::class,
                'choice_label' => function ($bookableTimeSlot) {
                    return $bookableTimeSlot->getStartDateTime()->format('d.m.Y h\hi');
                }
            ])
            ->add('visitors', CollectionType::class, [
                'entry_type' => VisitorType::class,
                'label' => 'entity.booking.visitors',
                'allow_add' => true,
                'by_reference' => false,
                'entry_options' => ['label' => false]
            ])
        ;
    }

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

我的访客实体(有点简化):

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

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

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

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

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

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

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

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getFirstName(): ?string
    {
        return $this->firstName;
    }

    public function setFirstName(string $firstName): self
    {
        $this->firstName = $firstName;

        return $this;
    }

    public function getLastName(): ?string
    {
        return $this->lastName;
    }

    public function setLastName(string $lastName): self
    {
        $this->lastName = $lastName;

        return $this;
    }

    public function getPhone(): ?string
    {
        return $this->phone;
    }

    public function setPhone(string $phone): self
    {
        $this->phone = $phone;

        return $this;
    }

    public function getBooking(): ?Booking
    {
        return $this->booking;
    }

    public function setBooking(?Booking $booking): self
    {
        $this->booking = $booking;

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(?string $email): self
    {
        $this->email = $email;

        return $this;
    }
}

最后是我的 VisitorType 表单(有点简化):

class VisitorType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName', TextType::class, [
                'label' => 'entity.visitor.first-name',
            ])
            ->add('lastName', TextType::class, [
                'label' => 'entity.visitor.last-name',
            ])
            ->add('phone', TextType::class, [
                'label' => 'entity.visitor.phone-number',
                'required' => false,
            ])
            ->add('email', TextType::class, [
                'label' => 'entity.visitor.email',
                'required' => false,
                'constraints' => [
                    new Email()
                ]
            ])
        ;
    }

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

我尝试向电子邮件和电话字段添加一个表达式约束,如下所示:

new Expression([
    'expression' => 'this.getPhone() == null && this.getEmail() == null'
])

还尝试直接向实体添加约束,但对我来说似乎没有任何工作正常。

任何帮助将不胜感激。

更新 我没有指定这一点,但我的问题来自于我想从另一个将 VisitorType 添加为 CollectionType 的表单验证 VisitorType 表单。

【问题讨论】:

    标签: forms constraints symfony4


    【解决方案1】:

    尝试回调

    /**
     * @Assert\Callback
     */
    public function validate(ExecutionContextInterface $context, $payload)
    {
    
        if (null === $this->getEmail() && null === $this->getPhone())
            $context->buildViolation('Your message here.')
                ->atPath('email')
                ->addViolation();
    
       // you can add onther "if" if you like
    
    }
    

    【讨论】:

    • 这在我创建访问者时效果很好,但是当我从另一个表单中调用访问者类型作为 CollectionType 时就不行了
    • 为其他实体中的关系添加 Assert\Valid
    • 我做到了,现在我有一个新错误:警告:get_class() 期望参数 1 是对象,给定字符串所有这些都非常令人沮丧。我知道我越来越近了,但还没有。
    • @hour: 已回答第一个问题。随时帮助解决新问题;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    • 2017-05-02
    • 1970-01-01
    相关资源
    最近更新 更多