Symfony2: Cara mendapatkan kesalahan validasi formulir setelah mengikat permintaan ke formulir

110

Inilah saveActionkode saya (di mana formulir meneruskan data ke)

public function saveAction()
{
    $user = OBUser();

    $form = $this->createForm(new OBUserType(), $user);

    if ($this->request->getMethod() == 'POST')
    {
        $form->bindRequest($this->request);
        if ($form->isValid())
            return $this->redirect($this->generateUrl('success_page'));
        else
            return $this->redirect($this->generateUrl('registration_form'));
    } else
        return new Response();
}

Pertanyaan saya adalah: bagaimana saya mendapatkan kesalahan jika $form->isValid()kembali false?

putolaruan.dll
sumber

Jawaban:

117

Anda memiliki dua kemungkinan cara untuk melakukannya:

  • jangan mengarahkan pengguna saat terjadi kesalahan dan menampilkan {{ form_errors(form) }}dalam file template
  • mengakses array kesalahan sebagai $form->getErrors()
nefo_x
sumber
22
Saya melakukan hal kedua yang Anda sarankan tetapi form-> getErrors () mengembalikan array kosong.
putolaruan
2
Saya juga melakukan yang pertama (w / php templates <? Php echo $ view ['form'] -> error ($ form)?>) Tetapi masih kosong!
putolaruan
59
@mives Anda harus disetel error_bubblingke true dalam jenis formulir Anda dengan secara eksplisit menyetel opsi untuk setiap bidang.
kgilden
5
Jika Anda menggunakan validator khusus, Symfony tidak mengembalikan kesalahan yang dibuat oleh validator tersebut di $ form-> getErrors ().
Jay Sheth
13
Anda juga $form->getErrors(true)dapat memasukkan kesalahan formulir anak juga
Chris
103

Symfony 2.3 / 2.4:

Fungsi ini mendapatkan semua kesalahan. Yang ada di formulir seperti "Token CSRF tidak valid. Harap coba kirim ulang formulir." serta tambahan error berupa children yang tidak memiliki error menggelembung.

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = $this->getErrorMessages($child);
        }
    }

    return $errors;
}

Untuk mendapatkan semua kesalahan sebagai string:

$string = var_export($this->getErrorMessages($form), true);

Symfony 2.5 / 3.0:

$string = (string) $form->getErrors(true, false);

Dokumen:
https://github.com/symfony/symfony/blob/master/UPGRADE-2.5.md#form https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#form (di bagian bawah: The method Form::getErrorsAsString() was removed)

Balik
sumber
1
Ini sepertinya jawaban paling benar untuk Symfony 2.4 saat ini.
Slava Fomin II
@Flip berfungsi dengan sempurna pada 2.5
iaryo
1
Jawaban bagus TAPI $errors[$child->getName()] = $this->getErrorMessages($child);melontarkan pengecualian, karena getErrorMessages hilang dari komponen Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller . Jadi saya menggantinya dengan$form_errors[$child->getName()] = $child->getErrorsAsString();
Ahad Ali
3
@AhadAli ini adalah fungsi rekursif, jadi ketika Anda meletakkan potongan kode di kelas di mana Anda membutuhkan fungsionalitas ini, ia akan dapat memanggil dirinya sendiri. "Perbaikan" Anda akan mencegah Anda mencapai formulir bertingkat. Ini berhasil untuk 37 orang lainnya, itu harus bekerja untuk Anda juga;)
Balik
@Flip Ah maaf saya buruk, saya hanya melihat $this->getErrorMessages()dan saya pikir itu dipanggil langsung di dalam pengontrol dan bagian dari api Symfony.
Ahad Ali
47

Di bawah ini adalah solusi yang berhasil untuk saya. Fungsi ini ada di pengontrol dan akan mengembalikan larik terstruktur dari semua pesan kesalahan dan bidang yang menyebabkannya.

Symfony 2.0:

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();
    foreach ($form->getErrors() as $key => $error) {
        $template = $error->getMessageTemplate();
        $parameters = $error->getMessageParameters();

        foreach($parameters as $var => $value){
            $template = str_replace($var, $value, $template);
        }

        $errors[$key] = $template;
    }
    if ($form->hasChildren()) {
        foreach ($form->getChildren() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    }

    return $errors;
}

Symfony 2.1 dan yang lebih baru:

private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();

    if ($form->hasChildren()) {
        foreach ($form->getChildren() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    } else {
        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }   
    }

    return $errors;
}
Icode4food
sumber
5
Peningkatan gist.github.com/2011671 tetapi masih bukan yang saya inginkan. Saya ingin kunci array menjadi nama bidang, tetapi sebenarnya tidak.
umpirsky
9
@SalmanPK Twig tidak direferensikan dimanapun dalam kode di atas. Saya tidak percaya saya mengerti komentar Anda.
Icode4food
1
Berikut adalah perbaikan untuk inti sebelumnya, ini berfungsi di Symfony 2.1.7. gist.github.com/WishCow/5101428
K. Norbert
Sepertinya ada kesalahan ketik $this->getFormErrorsharus $this->getErrorMessagesdalam sampel Anda di Symfony2.1
Mick
@umpirsky Untuk mendapatkan nama field, saya mendapatkan ini: $ child-> getConfig () -> getOptions () ['label'] Butuh waktu lama untuk mencari tahu ...
jsgoupil
35

Gunakan Validator untuk mendapatkan kesalahan untuk entitas tertentu

if( $form->isValid() )
{
    // ...
}
else
{
    // get a ConstraintViolationList
    $errors = $this->get('validator')->validate( $user );

    $result = '';

    // iterate on it
    foreach( $errors as $error )
    {
        // Do stuff with:
        //   $error->getPropertyPath() : the field that caused the error
        //   $error->getMessage() : the error message
    }
}

Referensi API:

Olivier 'Ölbaum' Scherler
sumber
Terima kasih, yang saya butuhkan +1
Phill Pafford
4
Saya tidak yakin bahwa ini adalah pendekatan yang baik untuk memvalidasi setiap entitas secara terpisah. Bagaimana jika Anda memiliki bentuk hierarki yang kompleks? Masalah kedua adalah validasi terjadi dua kali.
Slava Fomin II
3
@SlavaFominII - "Masalah kedua adalah validasi terjadi dua kali" - Poin bagus, tidak ada yang diperbarui! Daftar kesalahan yang sama setelahnya!
BentCoder
20

Untuk mendapatkan pesan yang tepat (dapat diterjemahkan), saat ini menggunakan SF 2.6.3, berikut adalah fungsi terakhir saya (karena tidak ada satu pun di atas yang tampaknya berfungsi lagi):

 private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();
    foreach ($form->getErrors(true, false) as $error) {
        // My personnal need was to get translatable messages
        // $errors[] = $this->trans($error->current()->getMessage());
        $errors[] = $error->current()->getMessage();
    }

    return $errors;
}

karena metode Form :: getErrors () sekarang mengembalikan turunan FormErrorIterator , kecuali Anda mengganti argumen kedua ($ flatten) menjadi true . (Ini kemudian akan mengembalikan instance FormError , dan Anda harus memanggil metode getMessage () secara langsung, tanpa metode current ():

 private function getErrorMessages(\Symfony\Component\Form\Form $form) {      
    $errors = array();
    foreach ($form->getErrors(true, true) as $error) {
        // My personnal need was to get translatable messages
        // $errors[] = $this->trans($error->getMessage());
        $errors[] = $error->getMessage();
    }

    return $errors;
}

)

Hal yang paling penting sebenarnya adalah menyetel argumen pertama menjadi benar untuk mendapatkan kesalahan. Membiarkan argumen kedua ($ flatten) ke nilai defaultnya ( true ) akan mengembalikan contoh FormError , sementara itu akan mengembalikan contoh FormErrorIterator ketika disetel ke false.

Cedo
sumber
Bagus, menggunakan barang yang sama.
Organik Rusak
bukan? :) @KidBinary
Cedo
Benar-benar cantik, sobat
:)
Opsi yang lebih baik adalah: $ error = array_map (function ($ item) {return $ item-> current () -> getMessage ();}, $ campaignForm-> getErrors (true, false));
Enrique Quero
Solusi yang bagus untuk Symfony 2.7
Yann Chabot
16

Untuk pesan flash saya, saya senang $form->getErrorsAsString()

Edit (dari Benji_X80): Untuk penggunaan SF3 $form->getErrors(true, false);

Tjorriemorrie
sumber
3
Saya tahu ini jawaban lama tetapi untuk referensi di masa mendatang: This method should only be used to help debug a form.( sumber )
cheesemacfly
getErrorsAsString () tidak digunakan lagi di 3.0, gunakan: $ form-> getErrors (true, false);
Benji_X80
15

Fungsi untuk symfony 2.1 dan yang lebih baru, tanpa fungsi yang tidak digunakan lagi:

/**
 * @param \Symfony\Component\Form\Form $form
 *
 * @return array
 */
private function getErrorMessages(\Symfony\Component\Form\Form $form)
{
    $errors = array();

    if ($form->count() > 0) {
        foreach ($form->all() as $child) {
            /**
             * @var \Symfony\Component\Form\Form $child
             */
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }
    } else {
        /**
         * @var \Symfony\Component\Form\FormError $error
         */
        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }
    }

    return $errors;
}
stwe
sumber
Saya akan memposting jawaban baru untuk posting ini tetapi Anda tampaknya telah mengalahkan saya sampai habis. Saya harus melihat-lihat kode sumber untuk mencari tahu mengapa pemanggilan metode tidak ditemukan.
Dr.Knowitall
Saya perhatikan ini tidak menarik kesalahan dari item yang memiliki kesalahan menggelembung disetel ke true. SF2.4
kinghfb
@stwe apa tujuan dari IFpernyataan pertama ? Mengapa itu saling eksklusif? Sejauh yang saya bisa lihat: bentuk bisa memiliki kesalahannya sendiri seperti halnya anak-anak.
Slava Fomin II
4

Pesan Kesalahan Formulir yang Diterjemahkan (Symfony2.1)

Saya telah berjuang keras untuk menemukan informasi ini, jadi saya pikir perlu menambahkan catatan tentang terjemahan kesalahan formulir.

@Icode4foodjawaban akan mengembalikan semua kesalahan formulir. Namun, array yang dikembalikan tidak memperhitungkan pluralisasi atau terjemahan pesan .

Anda dapat memodifikasi foreach loop of @Icode4foodanswer menjadi combo:

  • Dapatkan semua kesalahan dari formulir tertentu
  • Kembalikan kesalahan yang diterjemahkan
  • Pertimbangkan pluralisasi jika perlu

Ini dia:

foreach ($form->getErrors() as $key => $error) {

   //If the message requires pluralization
    if($error->getMessagePluralization() !== null) {
        $errors[] = $this->container->get('translator')->transChoice(
            $error->getMessage(), 
            $error->getMessagePluralization(), 
            $error->getMessageParameters(), 
            'validators'
            );
    } 
    //Otherwise, we do a classic translation
    else {
        $errors[] = $this->container->get('translator')->trans(
            $error->getMessage(), 
            array(), 
            'validators'
            );
    }
}

Jawaban ini telah dikumpulkan dari 3 postingan berbeda:

Mick
sumber
Baru saja mencoba versi Anda dan berhasil Fatal Error: Call to undefined method Symfony\Component\Form\FormError::getMessagePluralization(). Saya curiga ini hanya untuk Symfony 2.1?
Czar Pino
4

SYMFONY 3.X

Metode SF 3.X lain yang diberikan di sini tidak berfungsi untuk saya karena saya dapat mengirimkan data kosong ke formulir (tetapi saya memiliki kendala NotNull / NotBlanck). Dalam hal ini string kesalahan akan terlihat seperti ini:

string(282) "ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be blank.
ERROR: This value should not be null.
name:
    ERROR: This value should not be blank.
"

Yang tidak terlalu berguna. Jadi saya membuat ini:

public function buildErrorArray(FormInterface $form)
{
    $errors = [];

    foreach ($form->all() as $child) {
        $errors = array_merge(
            $errors,
            $this->buildErrorArray($child)
        );
    }

    foreach ($form->getErrors() as $error) {
        $errors[$error->getCause()->getPropertyPath()] = $error->getMessage();
    }

    return $errors;
}

Yang akan mengembalikan itu:

array(7) {
  ["data.name"]=>
  string(31) "This value should not be blank."
  ["data.street"]=>
  string(31) "This value should not be blank."
  ["data.zipCode"]=>
  string(31) "This value should not be blank."
  ["data.city"]=>
  string(31) "This value should not be blank."
  ["data.state"]=>
  string(31) "This value should not be blank."
  ["data.countryCode"]=>
  string(31) "This value should not be blank."
  ["data.organization"]=>
  string(30) "This value should not be null."
}
sbouba.dll
sumber
3

Anda juga dapat menggunakan layanan validator untuk mendapatkan pelanggaran batasan:

$errors = $this->get('validator')->validate($user);
antoinet
sumber
6
Ini akan memvalidasi objek tetapi bukan formulirnya. Jika, misalnya, token CRSF adalah penyebab kesalahan, pesan tidak akan disertakan.
Icode4food
3

Pesan Kesalahan Formulir yang Diterjemahkan (Symfony2.3)

Versi saya untuk memecahkan masalah:

/src/Acme/MyBundle/Resources/config/services.yml

services:
    form_errors:
        class: Acme\MyBundle\Form\FormErrors

/src/Acme/MyBundle/Form/FormErrors.php

<?php
namespace Acme\MyBundle\Form;

class FormErrors
{
    public function getArray(\Symfony\Component\Form\Form $form)
    {
        return $this->getErrors($form);
    }

    private function getErrors($form)
    {
        $errors = array();

        if ($form instanceof \Symfony\Component\Form\Form) {

            // соберем ошибки элемента
            foreach ($form->getErrors() as $error) {

                $errors[] = $error->getMessage();
            }

            // пробежимся под дочерним элементам
            foreach ($form->all() as $key => $child) {
                /** @var $child \Symfony\Component\Form\Form */
                if ($err = $this->getErrors($child)) {
                    $errors[$key] = $err;
                }
            }
        }

        return $errors;
    }
}

/src/Acme/MyBundle/Controller/DefaultController.php

$form = $this->createFormBuilder($entity)->getForm();
$form_errors = $this->get('form_errors')->getArray($form);
return new JsonResponse($form_errors);

Di Symfony 2.5 Anda bisa mendapatkan semua kesalahan bidang dengan sangat mudah:

    $errors = array();
    foreach ($form as $fieldName => $formField) {
        foreach ($formField->getErrors(true) as $error) {
            $errors[$fieldName] = $error->getMessage();
        }
    }
Lebnik
sumber
3

Untuk Symfony 3.2 dan yang lebih baru gunakan ini,

public function buildErrorArray(FormInterface $form)
{
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = (string) $child->getErrors(true, false);
        }
    }
    return $errors;
}

Gunakan str_replace jika Anda ingin menyingkirkan teks ' Kesalahan: ' yang mengganggu di setiap teks deskripsi kesalahan.

$errors[$child->getName()] = str_replace('ERROR:', '', (string) $child->getErrors(true, false));
Anjana Silva
sumber
2

Jika Anda menggunakan validator khusus, Symfony tidak mengembalikan kesalahan yang dibuat oleh validator tersebut di $form->getErrors().$form->getErrorsAsString()akan mengembalikan semua kesalahan yang Anda butuhkan, tetapi sayangnya keluarannya diformat sebagai string, bukan array.

Metode yang Anda gunakan untuk mendapatkan semua kesalahan (terlepas dari mana asalnya), bergantung pada versi Symfony yang Anda gunakan.

Sebagian besar solusi yang disarankan melibatkan pembuatan fungsi rekursif yang memindai semua bentuk anak, dan mengekstrak kesalahan yang relevan ke dalam satu larik. Symfony 2.3 tidak memiliki $form->hasChildren()fungsi tersebut, tetapi ia memiliki $form->all().

Berikut adalah kelas pembantu untuk Symfony 2.3, yang dapat Anda gunakan untuk mengekstrak semua kesalahan dari bentuk apa pun. (Ini didasarkan pada kode dari komentar oleh yapro pada tiket bug terkait di akun github Symfony.)

namespace MyApp\FormBundle\Helpers;

use Symfony\Component\Form\Form;

class FormErrorHelper
{
    /**
     * Work-around for bug where Symfony (2.3) does not return errors from custom validaters,
     * when you call $form->getErrors().
     * Based on code submitted in a comment here by yapro:
     * https://github.com/symfony/symfony/issues/7205
     *
     * @param Form $form
     * @return array Associative array of all errors
     */
    public function getFormErrors($form)
    {
        $errors = array();

        if ($form instanceof Form) {
            foreach ($form->getErrors() as $error) {
                $errors[] = $error->getMessage();
            }

            foreach ($form->all() as $key => $child) {
                /** @var $child Form */
                if ($err = $this->getFormErrors($child)) {
                    $errors[$key] = $err;
                }
            }
        }

        return $errors;
    }
}

Kode panggilan:

namespace MyApp\ABCBundle\Controller;

use MyApp\FormBundle\Helpers;

class MyController extends Controller
{
    public function XYZAction()
    {
        // Create form.

        if (!$form->isValid()) {
            $formErrorHelper = new FormErrorHelper();
            $formErrors = $formErrorHelper->getFormErrors($form);

            // Set error array into twig template here.
        }
    }

}
Jay Sheth
sumber
2

Berdasarkan jawaban @Jay Seth, saya membuat versi class FormErrors khusus untuk Ajax Forms:

// src/AppBundle/Form/FormErrors.php
namespace AppBundle\Form;

class FormErrors
{

    /**
     * @param \Symfony\Component\Form\Form $form
     *
     * @return array $errors
     */
    public function getArray(\Symfony\Component\Form\Form $form)
    {
        return $this->getErrors($form, $form->getName());
    }

    /**
     * @param \Symfony\Component\Form\Form $baseForm
     * @param \Symfony\Component\Form\Form $baseFormName
     *
     * @return array $errors
     */
    private function getErrors($baseForm, $baseFormName) {
        $errors = array();
        if ($baseForm instanceof \Symfony\Component\Form\Form) {
            foreach($baseForm->getErrors() as $error) {
                $errors[] = array(
                    "mess"      => $error->getMessage(),
                    "key"       => $baseFormName
                );
            }

            foreach ($baseForm->all() as $key => $child) {
                if(($child instanceof \Symfony\Component\Form\Form)) {
                    $cErrors = $this->getErrors($child, $baseFormName . "_" . $child->getName());
                    $errors = array_merge($errors, $cErrors);
                }
            }
        }
        return $errors;
    }
}

Penggunaan (misalnya dalam tindakan Anda):

$errors = $this->get('form_errors')->getArray($form);

Versi Symfony: 2.8.4

Contoh respon JSON:

{
    "success": false,
    "errors": [{
        "mess": "error_message",
        "key": "RegistrationForm_user_firstname"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_lastname"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_email"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_zipCode"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_user_password_password"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_terms"
    }, {
        "mess": "error_message2",
        "key": "RegistrationForm_terms"
    }, {
        "mess": "error_message",
        "key": "RegistrationForm_marketing"
    }, {
        "mess": "error_message2",
        "key": "RegistrationForm_marketing"
    }]
}

Objek kesalahan berisi bidang "kunci", yang merupakan id dari elemen DOM masukan, sehingga Anda dapat dengan mudah mengisi pesan kesalahan.

Jika Anda memiliki formulir anak di dalam formulir induk, jangan lupa untuk menambahkan cascade_validationopsi di dalam formulir induk setDefaults.

Perampok
sumber
1

Untuk Symfony 2.1 dan seterusnya untuk digunakan dengan tampilan kesalahan Twig, saya mengubah fungsi untuk menambahkan FormError daripada hanya mengambilnya, dengan cara ini Anda memiliki kontrol lebih besar atas kesalahan dan tidak harus menggunakan error_bubbling pada setiap input individu. Jika Anda tidak menyetelnya dengan cara di bawah ini {{form_errors (form)}} akan tetap kosong:

/**
 * @param \Symfony\Component\Form\Form $form
 *
 * @return void
 */
private function setErrorMessages(\Symfony\Component\Form\Form $form) {      

    if ($form->count() > 0) {
        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                if( isset($this->getErrorMessages($child)[0]) ) {
                    $error = new FormError( $this->getErrorMessages($child)[0] );
                    $form->addError($error);
                }
            }
        }
    }

}
Negeri Ajaib yang Direbus Keras
sumber
1

$ form-> getErrors () bekerja untuk saya.

ahyong
sumber
1

Saya datang dengan solusi ini. Ia bekerja dengan baik dengan Symfony 2.4 terbaru .

Saya akan mencoba memberikan beberapa penjelasan.

Menggunakan validator terpisah

Saya rasa itu ide yang buruk untuk menggunakan validasi terpisah untuk memvalidasi entitas dan mengembalikan pesan pelanggaran batasan, seperti yang disarankan oleh penulis lain.

  1. Anda perlu memvalidasi semua entitas secara manual, menentukan grup validasi, dll, dll. Dengan bentuk hierarki yang kompleks, ini sama sekali tidak praktis dan akan lepas kendali.

  2. Dengan cara ini Anda akan memvalidasi formulir dua kali: sekali dengan formulir dan sekali dengan validator terpisah. Ini adalah ide yang buruk dari perspektif kinerja.

Saya menyarankan untuk mengulang jenis formulir secara rekursif dengan anak-anaknya untuk mengumpulkan pesan kesalahan.

Menggunakan beberapa metode yang disarankan dengan pernyataan IF eksklusif

Beberapa jawaban yang disarankan oleh penulis lain berisi pernyataan IF yang saling eksklusif seperti ini: if ($form->count() > 0)atau if ($form->hasChildren()).

Sejauh yang saya bisa lihat, setiap bentuk bisa memiliki kesalahan seperti halnya anak-anak. Saya tidak ahli dengan komponen Formulir Symfony , tetapi dalam praktiknya Anda tidak akan mendapatkan beberapa kesalahan dari formulir itu sendiri, seperti kesalahan perlindungan CSRF atau kesalahan bidang tambahan . Saya menyarankan untuk menghapus pemisahan ini.

Menggunakan struktur hasil yang didenormalisasi

Beberapa penulis menyarankan untuk meletakkan semua kesalahan di dalam array biasa. Jadi semua pesan kesalahan dari formulir itu sendiri dan dari anaknya akan ditambahkan ke larik yang sama dengan strategi pengindeksan yang berbeda: berbasis nomor untuk kesalahan tipe itu sendiri dan berbasis nama untuk kesalahan anak. Saya menyarankan untuk menggunakan struktur data yang dinormalisasi dalam bentuk:

errors:
    - "Self error"
    - "Another self error"

children
    - "some_child":
        errors:
            - "Children error"
            - "Another children error"

        children
            - "deeper_child":
                errors:
                    - "Children error"
                    - "Another children error"

    - "another_child":
        errors:
            - "Children error"
            - "Another children error"

Hasil dengan cara itu dapat dengan mudah diulang nanti.

Solusi saya

Jadi, inilah solusi saya untuk masalah ini:

use Symfony\Component\Form\Form;

/**
 * @param Form $form
 * @return array
 */
protected function getFormErrors(Form $form)
{
    $result = [];

    // No need for further processing if form is valid.
    if ($form->isValid()) {
        return $result;
    }

    // Looking for own errors.
    $errors = $form->getErrors();
    if (count($errors)) {
        $result['errors'] = [];
        foreach ($errors as $error) {
            $result['errors'][] = $error->getMessage();
        }
    }

    // Looking for invalid children and collecting errors recursively.
    if ($form->count()) {
        $childErrors = [];
        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                $childErrors[$child->getName()] = $this->getFormErrors($child);
            }
        }
        if (count($childErrors)) {
            $result['children'] = $childErrors;
        }
    }

    return $result;
}

Saya harap ini akan membantu seseorang.

Slava Fomin II
sumber
@weaverryan dapatkah Anda melihat solusi saya? Apakah valid, atau adakah kekurangan atau kesalahpahaman? Terima kasih!
Slava Fomin II
1

SIMFONI 3.1

Saya hanya menerapkan metode statis untuk menangani tampilan kesalahan

static function serializeFormErrors(Form\Form $form)
{
    $errors = array();
    /**
     * @var  $key
     * @var Form\Form $child
     */
    foreach ($form->all() as $key => $child) {
        if (!$child->isValid()) {
            foreach ($child->getErrors() as $error) {
                $errors[$key] = $error->getMessage();
            }
        }
    }

    return $errors;
}

Berharap bisa membantu

Shigiang Liu
sumber
1

Symfony 3 dan yang lebih baru

Saya baru-baru ini membuat fungsi yang membuat pohon kesalahan formulir. Ini akan membantu untuk mengembalikan daftar kesalahan kembali ke ujung depan. Ini didasarkan pada jenis formulir yang memiliki:

'error_bubbling' => false

Kode:

public static function getFormErrorsTree(FormInterface $form): array
{
    $errors = [];

    if (count($form->getErrors()) > 0) {
        foreach ($form->getErrors() as $error) {
            $errors[] = $error->getMessage();
        }
    } else {
        foreach ($form->all() as $child) {
            $childTree = self::getFormErrorsTree($child);

            if (count($childTree) > 0) {
                $errors[$child->getName()] = $childTree;
            }
        }
    }

    return $errors;
}

Keluaran:

Array
(
    [name] => Array
        (
            [0] => This value is not valid.
        )

    [emails] => Array
        (
            [0] => Array
                (
                    [0] => Given e-mail is not valid.
                    [1] => Given e-mail is not valid #2.
                )
            [1] => Array
                (
                    [0] => Given e-mail is not valid.
                    [1] => Given e-mail is not valid #2.
                )

        )

)

Perhatian : Saya tahu bahwa kesalahan dari bidang tingkat yang lebih dalam dapat ditimpa jika tingkat yang lebih tinggi memiliki kesalahan, tetapi ini ditujukan untuk penggunaan saya.

Krzysztof Trzos
sumber
Sempurna untuk var_dump, terima kasih
ReaperSoon
0

Untuk Symfony 2.1:

Ini adalah solusi terakhir saya dengan mengumpulkan banyak solusi lain:

protected function getAllFormErrorMessages($form)
{
    $retval = array();
    foreach ($form->getErrors() as $key => $error) {
        if($error->getMessagePluralization() !== null) {
            $retval['message'] = $this->get('translator')->transChoice(
                $error->getMessage(), 
                $error->getMessagePluralization(), 
                $error->getMessageParameters(), 
                'validators'
            );
        } else {
            $retval['message'] = $this->get('translator')->trans($error->getMessage(), array(), 'validators');
        }
    }
    foreach ($form->all() as $name => $child) {
        $errors = $this->getAllFormErrorMessages($child);
        if (!empty($errors)) {
           $retval[$name] = $errors; 
        }
    }
    return $retval;
}
Fernando PG
sumber