如何解决具有组的Valid约束的Symfony条件验证
至少对于我来说,我遇到了非常奇怪的Symfony行为。 我有嵌套表格的表格类型。我仅在某些情况下需要验证此嵌套表单。
这就是为什么我将验证组添加到Valid()约束的原因。 如果我使用相同的组例如。 TextType,它按预期工作。如果我从Valid()中删除组,它也可以工作。因此,这意味着Valid()约束本身会起作用,而在使用验证组时它就不会起作用。
$builder
->add('test',TextType::class,[
'mapped' => false,'constraints' => [new NotBlank(['groups' => 'SenderAddress'])],])
->add('senderAddress',AddressType::class,[
'label' => false,'constraints' => [new Valid(['groups' => 'SenderAddress'])],])
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'validation_groups' => function (FormInterface $form) {
if (!$form->get('senderAddresses')->getData()) {
return ['Default','SenderAddress'];
}
return ['Default'];
},]);
}
因此,如果senderAddresses中没有任何内容,并且
- test 字段为空, test 字段已正确验证,并且使用NotBlank()暴力
- senderAddress不会显示任何暴力,即使字段为空?!
但是,当我尝试删除senderAddress的组验证时,它可以按预期工作。 我在做什么错了?
->add('senderAddress',[
'label' => false,'constraints' => [new Valid()],//but this is not how I want it!
])
编辑: 这些是我处理的对象
CalculationType的实体订单
<?php
namespace App\Entity;
use App\Repository\OrderRepository;
use App\Traits\IdentifierTrait;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass=OrderRepository::class)
* @ORM\Table(name="`order`")
*/
class Order
{
use IdentifierTrait;
public const STATUSES = [
'order.statuses.calculation' => self::STATUS_CALCULATION,'order.statuses.created' => self::STATUS_CREATED,];
public const STATUS_CALCULATION = 1;
public const STATUS_CREATED = 2;
/**
* @ORM\ManyToOne(targetEntity="Address",cascade={"persist"})
*
* @var Address
*/
private Address $senderAddress;
/**
* @ORM\ManyToOne(targetEntity="Address",cascade={"persist"})
*
* @var Address
*/
private Address $recipientAddress;
/**
* @ORM\ManyToOne(targetEntity="Package",cascade={"persist"})
* @Assert\Valid()
*
* @var Package
*/
private Package $package;
/**
* @ORM\Column(type="datetime")
*
* @var DateTime
*/
private DateTime $createdAt;
/**
* @ORM\Column(type="integer",length=1,options={"unsigned": true})
*
* @var int
*/
protected int $status = self::STATUS_CALCULATION;
/**
* @ORM\Column(type="text",length=255,nullable=TRUE)
*
* @var null|string
*/
private ?string $serviceType = null;
/**
* @ORM\ManyToOne(targetEntity=User::class)
*
* @var User
*/
private User $user;
/**
* Order constructor.
*/
public function __construct()
{
$this->createdAt = new DateTime('now');
}
/**
* @return Address
*/
public function getSenderAddress(): Address
{
return $this->senderAddress;
}
/**
* @param Address $senderAddress
*/
public function setSenderAddress(Address $senderAddress): void
{
$this->senderAddress = $senderAddress;
}
/**
* @return Address
*/
public function getRecipientAddress(): Address
{
return $this->recipientAddress;
}
/**
* @param Address $recipientAddress
*/
public function setRecipientAddress(Address $recipientAddress): void
{
$this->recipientAddress = $recipientAddress;
}
/**
* @return Package
*/
public function getPackage(): Package
{
return $this->package;
}
/**
* @param Package $package
*/
public function setPackage(Package $package): void
{
$this->package = $package;
}
/**
* @return string|null
*/
public function getServiceType(): ?string
{
return $this->serviceType;
}
/**
* @param string|null $serviceType
*/
public function setServiceType(?string $serviceType): void
{
$this->serviceType = $serviceType;
}
/**
* @return DateTime
*/
public function getCreatedAt(): DateTime
{
return $this->createdAt;
}
/**
* @param DateTime $createdAt
*/
public function setCreatedAt(DateTime $createdAt): void
{
$this->createdAt = $createdAt;
}
/**
* @return int
*/
public function getStatus(): int
{
return $this->status;
}
/**
* @param int $status
*/
public function setStatus(int $status): void
{
$this->status = $status;
}
/**
* @return User
*/
public function getUser(): User
{
return $this->user;
}
/**
* @param User $user
*/
public function setUser(User $user): void
{
$this->user = $user;
}
}
AddressType的实体地址
<?php
namespace App\Entity;
use App\Repository\AddressRepository;
use App\Traits\IdentifierTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Intl\Countries;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass=AddressRepository::class)
*/
class Address
{
use IdentifierTrait;
public const TYPES = [
'address.types.sender' => self::TYPE_SENDER,'address.types.recipient' => self::TYPE_RECIPIENT,];
public const TYPE_SENDER = 1;
public const TYPE_RECIPIENT = 2;
/**
* @ORM\ManyToOne(targetEntity=User::class,inversedBy="addresses")
*
* @var User|null
*/
private ?User $user;
/**
* @ORM\Column(type="string",length=100,nullable=true)
* @Assert\Length(
* max="100"
* )
*
* @var string|null
*/
private ?string $name = null;
/**
* @ORM\Column(type="string",length=150)
* @Assert\NotBlank()
* @Assert\Length(
* max="150"
* )
*
* @var string|null
*/
private ?string $street = null;
/**
* @ORM\Column(type="string",length=100)
* @Assert\NotBlank()
* @Assert\Length(
* max="100"
* )
*
* @var string|null
*/
private ?string $city = null;
/**
* @ORM\Column(type="string",length=15)
* @Assert\NotBlank()
* @Assert\Length(
* max="15"
* )
*
* @var string|null
*/
private ?string $postalCode = null;
/**
* @ORM\Column(type="string",length=3)
* @Assert\NotBlank()
* @Assert\Length(
* max="3"
* )
*
* @var string|null
*/
private ?string $country = null;
/**
* @ORM\Column(type="string",length=3,nullable=true)
*
* @var string|null
*/
private ?string $province = null;
/**
* @ORM\Column(type="integer",options={"unsigned": true})
*
* @var int
*/
protected int $type = self::TYPE_SENDER;
/**
* Address constructor.
*
* @param int $type
* @param User|null $user
*/
public function __construct(int $type = self::TYPE_SENDER,User $user = null)
{
$this->type = $type;
$this->user = $user;
}
/**
* @return User|null
*/
public function getUser(): ?User
{
return $this->user;
}
/**
* @param User|null $user
*/
public function setUser(?User $user): void
{
$this->user = $user;
}
/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @param string|null $name
*/
public function setName(?string $name): void
{
$this->name = $name;
}
/**
* @return string|null
*/
public function getStreet(): ?string
{
return $this->street;
}
/**
* @param string|null $street
*/
public function setStreet(?string $street): void
{
$this->street = $street;
}
/**
* @return string|null
*/
public function getCity(): ?string
{
return $this->city;
}
/**
* @param string|null $city
*/
public function setCity(?string $city): void
{
$this->city = $city;
}
/**
* @return string|null
*/
public function getPostalCode(): ?string
{
return $this->postalCode;
}
/**
* @param string|null $postalCode
*/
public function setPostalCode(?string $postalCode): void
{
$this->postalCode = $postalCode;
}
/**
* @return string|null
*/
public function getCountry(): ?string
{
return $this->country;
}
/**
* @param string|null $country
*/
public function setCountry(?string $country): void
{
$this->country = $country;
}
/**
* Get country name
*/
public function getCountryName(): string
{
return Countries::getName($this->country);
}
/**
* @return string|null
*/
public function getProvince(): ?string
{
return $this->province;
}
/**
* @param string|null $province
*/
public function setProvince(?string $province): void
{
$this->province = $province;
}
/**
* Get full description
*
* @return string
*/
public function getFullDescription(): string
{
return ($this->name ? ($this->name . ' - ') : '') . $this->street . ',' . $this->postalCode . ' ' . $this->city . ',' . $this->getCountryName();
}
/**
* @return int
*/
public function getType(): int
{
return $this->type;
}
/**
* @param int $type
*/
public function setType(int $type): void
{
$this->type = $type;
}
}
CalculationType
<?php
namespace App\Form;
use App\Entity\Address;
use App\Entity\User;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints\Valid;
class CalculationType extends AbstractType
{
/**
* @var UserInterface|User|null
*/
private ?UserInterface $user;
/**
* CalculationFormType constructor.
*
* @param Security $security
*/
public function __construct(Security $security)
{
$this->user = $security->getUser();
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*
*/
public function buildForm(FormBuilderInterface $builder,array $options): void
{
$builder
->add('senderAddress',[
'label' => false,'constraints' => [new Valid(['groups' => 'NotNullAddress'])],//todo doesnt work
])
->add('recipientAddress',//todo doesnt work
'show_name' => false,])
->add('package',PackageType::class,['label' => false])
->add('calculate',SubmitType::class,[
'label' => 'order.calculate',]);
$this->addressesField($builder,'senderAddresses',Address::TYPE_SENDER);
$this->addressesField($builder,'recipientAddresses',Address::TYPE_RECIPIENT);
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'validation_groups' => static function (FormInterface $form) {
if (!$form->get('senderAddresses')->getData()) {
return ['Default','NotNullAddress'];
}
return ['Default'];
},]);
}
/**
* Addresses field
*
* @param FormBuilderInterface $builder
* @param string $childName
* @param int $type
*/
private function addressesField(FormBuilderInterface $builder,string $childName,int $type): void
{
$builder->add($childName,EntityType::class,[
'class' => Address::class,'mapped' => false,'required' => false,'placeholder' => 'order.newAddress','choice_label' => 'fullDescription','query_builder' => function (EntityRepository $er) use ($type) {
return $er->createQueryBuilder('address')
->andWhere('address.user = :user')
->andWhere('address.type = ' . $type)
->setParameter('user',$this->user);
},'attr' => [
'class' => 'select-existing-address',],]);
}
}
AddressType
<?php
namespace App\Form;
use App\Entity\Address;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AddressType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*
* @throws \JsonException
*/
public function buildForm(FormBuilderInterface $builder,array $options): void
{
if ($options['show_name']) {
$builder->add('name');
}
$builder->add('street')
->add('city')
->add('postalCode')
->add('country',CountryType::class,[
'preferred_choices' => ['CZ','DE','IT','SK'],])
->add('province');
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Address::class,'show_name' => true,]);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。