一意のメールフィールドのみを持つ顧客エンティティがあります。お客様のメールアドレスを編集しようとしていますが、検証は正常に機能します。しかし、私はこれを私のコントローラーに持っています:
_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: ~
_
わかりました、ここで答えを見つけました:
フォームの子ごとに独自のエラーがあることがわかります。の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
エラーがエラーメッセージ文字列を解析せずに一意の競合が原因であると判断する方法を私はまだ疑問に思っています。
Symfony 2を使用している場合、デバッグの目的で$form->getErrorsAsString()
の代わりに$form->getErrors()
を使用できます。*
この答え から引用:
$form->getErrorsAsString()
は、フォームのデバッグにのみ使用する必要があります... $ form-> getErrors()の場合とは異なり、各子要素のエラーが含まれます。
更新1:
"最近のSymfonyバージョンでは、代わりに$form->getErrors(true, false);
を使用する必要があります。最初のパラメーターはdeep
に対応し、2番目はflatten
に対応します"(@Roubiによるコメントを参照)
次の解決策は私のために働きます:
$ form-> getErrors(true)
各フィールドで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);
}
}
}
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
)子からのエラー。
フォームが送信されて無効な場合、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();
}
これはデバッグのみを目的としています。フォーム、フォーム内のデータ、フィールドで発生する可能性のあるすべてのエラーが表示されます。本番モードでは、エラーをビューに返してユーザーに表示する必要があります。