web-dev-qa-db-ja.com

Symfony2:私のフォームはisValid()からfalseを返しますが、一意の制約条件からのgetErrors()の空の配列

一意のメールフィールドのみを持つ顧客エンティティがあります。お客様のメールアドレスを編集しようとしていますが、検証は正常に機能します。しかし、私はこれを私のコントローラーに持っています:

_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を返します。検証中にコントローラーの特定のエラーを確認する方法はありますか?また、コントローラーが空のエラー配列を返す理由を説明できますか?基本的に、そのエラーが発生した場合は「マージ」オプションを提供したいと思います。

編集:ここにformtypeがあります:

_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';
    }
}
_

そして、twigテンプレート:

_{% 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: ~
_
15

わかりました、ここで答えを見つけました:

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

エラーがエラーメッセージ文字列を解析せずに一意の競合が原因であると判断する方法を私はまだ疑問に思っています。

4

Symfony 2を使用している場合、デバッグの目的で$form->getErrorsAsString()の代わりに$form->getErrors()を使用できます。*

この答え から引用:

$form->getErrorsAsString()は、フォームのデバッグにのみ使用する必要があります... $ form-> getErrors()の場合とは異なり、各子要素のエラーが含まれます。


更新1:

"最近のSymfonyバージョンでは、代わりに$form->getErrors(true, false);を使用する必要があります。最初のパラメーターはdeepに対応し、2番目はflattenに対応します"(@Roubiによるコメントを参照)

21
Denes Papp

次の解決策は私のために働きます:

$ form-> getErrors(true)

2
Shadi Akil

各フィールドでerror_bubblingを使用して、エラーを$フォームにバブリングできます。

そうでない場合は、エラーを先読みすることもできます

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);
                }
            }
}
1
Thomas Bennett

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)子からのエラー。

0
numerogeek

フォームが送信されて無効な場合、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();

}

これはデバッグのみを目的としています。フォーム、フォーム内のデータ、フィールドで発生する可能性のあるすべてのエラーが表示されます。本番モードでは、エラーをビューに返してユーザーに表示する必要があります。

0
Miguel Carvajal