Версия Symfony: 2.8.5
Контекст: У меня есть сущность Restaurant
который имеет отношения OneToOne с сущностью Coordinates
которые имеют несколько отношений с другими лицами, связанными с информацией о координатах. Я мой бэкэнд, я создаю форму, связанную с Restaurant
объект с пользовательской вложенной формой, связанной с Coordinates
,
Примечание: я использую 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
с закрытием (как описано в официальный документ) завести новый CoordinatesFR
экземпляр в случае пустых данных (все поля не заполнены). Но Вот, В этой статье (написанной создателем компонента формы 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;
}
Координаты субъекта
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();
},
));
}
}
Задача ещё не решена.
Других решений пока нет …