Symfony2 - Как остановить Form-> handleRequest от обнуления полей, которые не существуют в данных post
У меня есть форма, встроенная в Symfony, и при визуализации в представлении форма html может содержать или не содержать все поля в объекте формы (тип объекта имеет пару разных состояний, а не все поля в представлении).
Проблема заключается в том, что, когда форма обрабатывается в обработчике отправки, с помощью метода handleRequest() объекта формы, он сбрасывает любые свойства в сущности, которые не присутствуют в данных сообщения, до нуля, сдувая любое существующее значение.
Есть ли способ сказать Symfony не быть таким глупым и обрабатывать только поля, присутствующие в данных POST?
Или мне нужно клонировать объект перед вызовом handleRequest, а затем перебирать значения POST и копировать связанные значения из объекта post-handleRequest в клон pre-handleRequest объекта, поэтому я сохраняю поля, которые не указаны в данных POST.
уф! как вы можете видеть, это немного глупое решение, немного неприятная проблема, tbh.
Я мог бы понять, что symfony делает это, если объект был фактически созданным объектом, но он был загружен из БД, а затем вызван handleRequest - он должен быть достаточно разумным, чтобы знать, что объект уже инициализирован и заданы только поля переданные в данных POST.
Спасибо за любую помощь.
Привет
Steve.
Ответы
Ответ 1
Короче говоря, не используйте handleRequest
.
Вместо этого следует использовать submit
, а параметр clearMissing
- false.
Symfony/Component/Form/FormInterface
/**
* Submits data to the form, transforms and validates it.
*
* @param null|string|array $submittedData The submitted data.
* @param bool $clearMissing Whether to set fields to NULL
* when they are missing in the
* submitted data.
*
* @return FormInterface The form instance
*
* @throws Exception\AlreadySubmittedException If the form has already been submitted.
*/
public function submit($submittedData, $clearMissing = true);
Когда вы используете handleRequest
, он определяет, какие данные вы хотите отправить, а затем отправляет их с помощью $form->submit($data, 'PATCH' !== $method);
, что означает, что, если вы не отправили форму с помощью метода PATCH
, тогда она очистит поля.
Чтобы отправить форму самостоятельно без очистки, вы можете использовать...
$form->submit($request->get($form->getName()), false);
.. которые получают массив данных формы из запроса и отправляют его напрямую, но с параметром clear missing fields установлено значение false.
Ответ 2
Если у вашего объекта разные состояния, вы можете отразить это в своем типе формы.
Либо создайте несколько типов форм (возможно, используя наследование), содержащих различные настройки полей, и создайте требуемый файл в вашем контроллере.
Что-то вроде этого:
class YourState1FormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('someField')
;
}
}
class YourState2FormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('someOtherField')
;
}
}
Или передать параметр в один тип формы при создании в контроллере и адаптировать настройку поля в зависимости от состояния. Если вы не добавляете поля, которые не присутствуют, они не обрабатываются.
Что-то вроде этого:
class YourFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
if($options['state'] == 'state1') {
$builder
->add('someField')
;
} else if($options['state'] == 'state2') {
$builder
->add('someOtherField')
;
}
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'state' => 'state1'
));
}
}
Обновление
Другой подход, который вы можете применить для изменения формы на основе представленных данных, - это зарегистрировать прослушиватели событий в форме PRE_SET_DATA и POST_SUBMIT. Эти слушатели вызывают в разные моменты процесса подачи формы и позволяют изменять форму в зависимости от объекта данных, переданного в тип формы при создании формы (PRE_SET_DATA) или данных формы, представленных пользователем (POST_SUBMIT).
В документах можно найти объяснение и примеры .