Symfony检查表单验证中两个字段中的至少一个是否不为空 [英] Symfony Check if at least one of two fields isn't empty on form validation

查看:62
本文介绍了Symfony检查表单验证中两个字段中的至少一个是否不为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经想了好一阵子了,但仍然找不到解决我问题的方法。使用Symfony 4表单和约束条件,我无法设置检查方式,以使提交包含子表单的表单时两个字段中的至少一个不能为空。



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



我的BookingType形式(略微简化):

  class BookingType扩展AbstractType 
{
专用$ router;
私人$ translator;

公共功能__construct(UrlGeneratorInterface $ router,TranslatorInterface $ translator)
{
$ this-> router = $ router;
$ this-> translator = $ translator;
}

公共功能buildForm(FormBuilderInterface $ builder,array $ options)
{
$ builder
-> add('bookableTimeSlot',EntityType :: class,[
'label'=>'entity.booking.bookable-time-slot',
'class'=> BookableTimeSlot :: class,
'choice_label'= >函数($ bookableTimeSlot){
return $ bookableTimeSlot-> getStartDateTime()-> format('dmY h\hi');
}
])
-> add('visitors',CollectionType :: class,[
'entry_type'=> VisitorType :: class,
'label'=>'entity.booking.visitors',
'allow_add'=> true,
'by_reference'=> false,
'entry_options'=> ['label'=> false]
])
;
}

公共功能configureOptions(OptionsResolver $ resolver)
{
$ resolver-> setDefaults([
'data_class'=>预订: :class,
'user'=> User :: class,
]);
}
}

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

 <?php 

命名空间App\Entity;

使用Doctrine\ORM\Mapping作为ORM;
使用Symfony\Component\Validator\Constraints作为断言;
使用Symfony\组件\Validator\Context\ExecutionContextInterface;

/ **
* @ ORM\Entity(repositoryClass = App\Repository\VisitorRepository)
* /
类访问者
{
/ **
* @ ORM\Id()
* @ ORM\GeneratedValue()
* @ ORM\Column(type = integer)
* /
私人$ 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)
* /
私人电话;

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

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

公共函数getId():?int
{
return $ this-> id;
}

公共函数getFirstName():?string
{
return $ this-> firstName;
}

公共函数setFirstName(string $ firstName):self
{
$ this-> firstName = $ firstName;

返回$ this;
}

公共函数getLastName():?string
{
return $ this-> lastName;
}

公共函数setLastName(string $ lastName):self
{
$ this-> lastName = $ lastName;

返回$ this;
}

公共功能getPhone():? string
{
return $ this-> phone;
}

公共功能setPhone(string $ phone):自我
{
$ this-> phone = $ phone;

返回$ this;
}

公共函数getBooking():?预订
{
return $ this->预订;
}

公共功能setBooking(?Booking $ booking):自我
{
$ this-> booking = $ booking;

返回$ this;
}

公共函数getEmail():?string
{
return $ this-> email;
}

公共功能setEmail(?string $ email):self
{
$ this-> email = $ email;

返回$ this;
}
}

最后确定我的VisitorType表单(略有简化):

  class VisitorType扩展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'=>否,
'constraints'= >> [
新的Email()
]
])
;
}

公共函数configureOptions(OptionsResolver $ resolver)
{
$ resolver-> setDefaults([
'data_class'=> :class,
]);
}
}

我尝试将Expression约束添加到电子邮件和电话字段,看起来像这样:

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

也尝试将约束直接添加到实体,但对我而言似乎没有任何正常工作。



任何帮助将不胜感激。



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

解决方案

尝试回调

  / ** 
* @ Assert\Callback
* /
public function validate(ExecutionContextInterface $ context,$ payload)
{

if (null === $ this-> getEmail()&& null === $ this-> getPhone())
$ context-> buildViolation('您的消息在这里。')
-> atPath('email')
-> addViolation();

//如果您喜欢

},则可以添加其他如果,则


I've been turning this around in my head for quite a while now and still wasn't able to find a solution to my problem. Using Symfony 4 forms and constraints I'm unable to setup a check to say that at least one of two fields must not be empty when submitting form that contains a sub-form.

I have a Booking entity which contains a Visitor entity which has a phoneNumber property and a email property. I'd like to be able to create a Booking which has a "visitors" CollectionType (where I'm allowed to add visitors from the BookingType form).

My BookingType form (a bit simplified):

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,
        ]);
    }
}

My Visitor entity (a bit simplified):

<?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;
    }
}

And finaly my VisitorType form (a bit simplified):

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,
        ]);
    }
}

I've tried to add an Expression constraint to the email and phone field which looked something like this:

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

Also tried to add constraint directly to the entity, but nothing seems to work correctly for me.

Any help would be greatly appreciated.

UPDATE I haven't specified this, but my problem comes from the fact that I would like to validate the VisitorType form from another form which adds the VisitorType as a CollectionType.

解决方案

try with callback

/**
 * @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

}

这篇关于Symfony检查表单验证中两个字段中的至少一个是否不为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆