Symfony2: моя форма возвращает false из isValid(), но пустой массив для getErrors() из уникального условия ограничения
У меня есть объект Customer, который имеет только уникальное поле электронной почты. Я пытаюсь редактировать электронную почту клиента, и проверка достоверности работает. Однако у меня есть это в моем контроллере:
public function updateAction(Request $request, $id) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('AcmeDemoBundle:Customer')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Customer entity.');
}
$editForm = $this->createForm(new CustomerType(), $entity);
$editForm->bind($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('ticket_result'));
}
var_dump($editForm->getErrors());
return $this->render('AcmeDemoBundle:Customer:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
));
}
var_dump возвращает пустой массив, но валидатор устанавливает уникальную ошибку, а $editForm->isValid()
возвращает false. Есть ли способ проверить эту ошибку в контроллере во время проверки, также вы можете объяснить, почему он возвращает пустой массив ошибок? В принципе, я хотел бы предоставить опцию "merge", если эта ошибка возникает.
EDIT: вот форма формы:
namespace Acme\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CustomerType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('email', 'email', array('required'=>true))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Acme\DemoBundle\Entity\Customer',
'cascade_validation' => true,
));
}
public function getName() {
return 'acme_demobundle_customertype';
}
}
И шаблон ветки:
{% extends 'AcmeDemoBundle::layout.html.twig' %}
{% block body -%}
<h1>Customer edit</h1>
<form action="{{ path('customer_update', { 'id': entity.id }) }}" method="post" {{ form_enctype(edit_form) }}>
<input type="hidden" name="_method" value="PUT" />
{{ form_widget(edit_form) }}
<p>
<button type="submit">Edit</button>
</p>
</form>
{% endblock %}
Вот моя проверка:
Acme\DemoBundle\Entity\Customer:
constraints:
- Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
fields: email
message: "A customer under that email address already exists"
properties:
email:
- Email: ~
Ответы
Ответ 1
Хорошо, нашел ответ здесь:
Неверная форма Symfony2 без ошибок
Оказывается, каждый из форм имеет собственные ошибки. При выполнении var_dump
$editForm->getChildren()['email']->getErrors()
Я получаю:
array (size=1)
0 =>
object(Symfony\Component\Form\FormError)[531]
private 'message' => string 'A customer under that email address already exists' (length=50)
protected 'messageTemplate' => string 'A customer under that email address already exists' (length=50)
protected 'messageParameters' =>
array (size=0)
empty
protected 'messagePluralization' => null
Мне все еще интересно, как определить, что ошибка вызвана уникальным конфликтом без разбора строки сообщения об ошибке.
Ответ 2
Для целей отладки вы можете использовать $form->getErrorsAsString()
вместо $form->getErrors()
, если используете Symfony 2..
Цитата из этого ответа:
$form->getErrorsAsString()
следует использовать только для отладки формы... it будут содержать ошибки каждого дочернего элемента, что не имеет места $form- > getErrors().
ОБНОВЛЕНИЕ 1:
"В более поздних версиях Symfony вы должны использовать вместо этого $form->getErrors(true, false);
. Первый параметр соответствует deep
и второй - flatten
" (см. комментарий от @Roubi)
Ответ 3
Вы можете использовать error_bubbling в каждом поле, чтобы пузырить ошибку до вашей $form.
Если нет, вы также можете просмотреть ошибки
foreach ($children as $child) {
if ($child->hasErrors()) {
$vars = $child->createView()->getVars();
$errors = $child->getErrors();
foreach ($errors as $error) {
$this->allErrors[$vars["name"]][] = $this->convertFormErrorObjToString($error);
}
}
}
Ответ 4
В Symfony 2.3 вы можете использовать это:
if ($form->isValid()){
# Code...
} else {
foreach ($form->getIterator() as $key => $child) {
if ($child instanceof Form) {
foreach ($child->getErrors() as $error) {
$errors[$key] = $error->getMessage();
}
}
}
}
Это даст вам массив ($errors
) с ошибками от детей.
Ответ 5
Вы можете попытаться использовать функцию dump
, когда форма отправлена и недействительна. Я использую его следующим образом
if($form->isSubmited() && $form->isValid()){
//SAVE TO DATABASE AND DO YOUR STUFF
}else if($form->isSubmited()){
//SUBMITED BUT WITH ERRORS
dump($form->getErrors(true));
die();
}
Обратите внимание, что это только для целей отладки, оно покажет вам вашу форму, данные в ней и все ошибки, которые может иметь любое поле.
В режиме производства вы должны вернуть ошибку в представление и показать ее пользователю.