Symfony版本: 2.8.5
上下文:我有一个实体Restaurant
,它与实体Coordinates
有一个OneToOne关系,它与其他与坐标信息相关的实体有几个关系。我的后端我创建了一个与Restaurant
实体相关的表单,其中包含与Coordinates
相关的自定义嵌套表单。
Nota:我使用EasyAdminBundle来生成我的后端。
实体关系计划:
Restaurant
1 ________ 1 `Coordinates`
* ________ 1 `CoordinatesCountry`
1 ________ 1 `CoordinatesFR`
* ________ 1 `CoordinatesFRLane`
* ________ 1 `CoordinatesFRCity`
后端视图:
此时我尝试以下方案:
Coordinates
嵌套表单为空(空字段)。因此,在表单提交后,将显示验证消息(参见下图)。我编辑了上一个表单,这次我填写了Coordinates
嵌套表单的字段。提交表单后,新的Coordinates
实体会被充实,并且会在Restaurant
和Coordinates
之间创建关系。
我再次编辑上一个表单,这次我清除了Coordinates
嵌套表单的所有字段。验证未触发,我收到以下错误:
类型" FBN \ GuideBundle \ Entity \ CoordinatesFRCity"的预期参数, " NULL"给定
我在CoordinatesFRType
(请参阅下面的代码)中确切地说明,在我第一次使用带有闭包的empty_data
选项时触发验证消息(如official doc中所述) )如果数据为空(所有字段为空),则实例化新的CoordinatesFR
实例。但是here,在本文中(由Symfony表单组件的创建者编写),解释了(参见empty_data和datta mappers段落)empty_data
仅在创建对象时调用。所以我认为这就是为什么我的验证在版本的情况下不再起作用的原因。
问题:在编辑表单并清除所有嵌入表单时,为什么验证无效?
代码(只有必要):
餐厅实体
use Symfony\Component\Validator\Constraints as Assert;
class Restaurant
{
/**
* @ORM\OneToOne(targetEntity="FBN\GuideBundle\Entity\Coordinates", inversedBy="restaurant", cascade={"persist"})
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
* @Assert\Valid()
*/
private $coordinates;
}
协调实体
use Symfony\Component\Validator\Constraints as Assert;
class Coordinates
{
/**
* @ORM\ManyToOne(targetEntity="FBN\GuideBundle\Entity\CoordinatesCountry")
* @ORM\JoinColumn(nullable=false)
*/
private $coordinatesCountry;
/**
* @ORM\OneToOne(targetEntity="FBN\GuideBundle\Entity\CoordinatesFR", inversedBy="coordinates", cascade={"persist"})
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
* @Assert\Valid()
*/
private $coordinatesFR;
/**
* @ORM\OneToOne(targetEntity="FBN\GuideBundle\Entity\Restaurant", mappedBy="coordinates")
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $restaurant;
}
CoordinatesFR实体
use Symfony\Component\Validator\Constraints as Assert;
class CoordinatesFR extends CoordinatesISO
{
/**
* @ORM\ManyToOne(targetEntity="FBN\GuideBundle\Entity\CoordinatesFRLane")
* @ORM\JoinColumn(nullable=true)
* @Assert\NotBlank()
*/
private $coordinatesFRLane;
/**
* @ORM\ManyToOne(targetEntity="FBN\GuideBundle\Entity\CoordinatesFRCity")
* @ORM\JoinColumn(nullable=false)
* @Assert\NotBlank()
*/
private $coordinatesFRCity;
/**
* @ORM\OneToOne(targetEntity="FBN\GuideBundle\Entity\Coordinates", mappedBy="coordinatesFR")
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $coordinates;
}
Easy Admin配置(相当于RestaurantType)
easy_admin:
entities:
Restaurant:
class : FBN\GuideBundle\Entity\Restaurant
form:
fields:
- { property: 'coordinates', type: 'FBN\GuideBundle\Form\CoordinatesType' }
CoordinatesType
class CoordinatesType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('CoordinatesCountry', EntityType::class, array(
'class' => 'FBNGuideBundle:CoordinatesCountry',
'property' => 'country',
))
->add('coordinatesFR', CoordinatesFRType::class)
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'FBN\GuideBundle\Entity\Coordinates',
));
}
}
CoordinatesFRType
class CoordinatesFRType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('laneNum', TextType::class)
->add('coordinatesFRLane', EntityType::class, array(
'class' => 'FBNGuideBundle:CoordinatesFRLane',
'property' => 'lane',
'placeholder' => 'label.form.empty_value',
))
->add('laneName', TextType::class)
->add('miscellaneous', TextType::class)
->add('locality', TextType::class)
->add('metro', TextType::class)
->add('coordinatesFRCity', EntityType::class, array(
'class' => 'FBNGuideBundle:CoordinatesFRCity',
'property' => 'display',
'query_builder' => function (CoordinatesFRCityRepository $repo) {
return $repo->getAscendingSortedCitiesQueryBuilder();
},
'placeholder' => 'label.form.empty_value',
))
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'FBN\GuideBundle\Entity\CoordinatesFR',
// Ensures that validation error messages will be correctly displayed next to each field
// of the corresponding nested form (i.e if submission and CoordinatesFR nested form with all fields empty)
'empty_data' => function (FormInterface $form) {
return new CoordFR();
},
));
}
}