Quantcast
Channel: Active questions tagged symfony4 - Stack Overflow
Viewing all articles
Browse latest Browse all 3925

Symfony Check if at least one of two fields isn't empty on form validation of CollectionType

$
0
0

In a previous question (Symfony Check if at least one of two fields isn't empty on form validation) I had asked help for form validation using Callback. The answer given by @hous was right, but it doesn't work for elements in a CollectionType, reason why I'm opening a new question.

Based on the previous answer I have done the following:

Here is my "mother" Form:

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

Here is my "son" Form:

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

My "booking" (shortened) class:

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

And finally my "visitor" (shortened) class:

/** * @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();        }    }}

I've been able to workaround the problem by adding a property to my VisitorType form that I define with the Callback constraint on the phone value and then check it with a Callback constraint on the email field, but it doesn't seem very "good practice".

If I only try to call the Callback constraint I get the following error message: "Warning: get_class() expects parameter 1 to be object, string given"

Any help is highly appreciated!


Viewing all articles
Browse latest Browse all 3925

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>