Ich habe diese Lösung gefunden. Es funktioniert solide mit dem neuesten Symfony 2.4 .
Ich werde versuchen, einige Erklärungen zu geben.
Separaten Validator verwenden
Ich denke, es ist eine schlechte Idee, eine separate Validierung zu verwenden, um Entitäten zu validieren und Nachrichten über Einschränkungsverletzungen zurückzugeben, wie von anderen Autoren vorgeschlagen.
Sie müssen alle Entitäten manuell validieren, Validierungsgruppen angeben usw. usw. Bei komplexen hierarchischen Formularen ist dies überhaupt nicht praktikabel und gerät schnell außer Kontrolle.
Auf diese Weise validieren Sie das Formular zweimal: einmal mit Formular und einmal mit separatem Validator. Dies ist aus Sicht der Leistung eine schlechte Idee.
Ich schlage vor, den Formulartyp mit seinen untergeordneten Elementen rekursiv zu iterieren, um Fehlermeldungen zu sammeln.
Verwendung einiger vorgeschlagener Methoden mit exklusiver IF-Anweisung
Einige von anderen Autoren vorgeschlagene Antworten enthalten sich gegenseitig ausschließende IF-Anweisungen wie diese: if ($form->count() > 0)
oder if ($form->hasChildren())
.
Soweit ich sehen kann, kann jedes Formular sowohl Fehler als auch Kinder enthalten. Ich bin kein Experte für Symfony Forms- Komponenten, aber in der Praxis werden einige Fehler des Formulars selbst nicht angezeigt , z. B. CSRF-Schutzfehler oder zusätzliche Felder . Ich schlage vor, diese Trennung zu entfernen.
Denormalisierte Ergebnisstruktur verwenden
Einige Autoren schlagen vor, alle Fehler in ein einfaches Array einzufügen. Daher werden alle Fehlermeldungen des Formulars selbst und seiner untergeordneten Elemente mit unterschiedlichen Indizierungsstrategien zum selben Array hinzugefügt: nummerbasiert für typeneigene Fehler und namenbasiert für untergeordnete Fehler. Ich schlage vor, eine normalisierte Datenstruktur des Formulars zu verwenden:
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"
Auf diese Weise kann das Ergebnis später leicht wiederholt werden.
Meine Lösung
Hier ist meine Lösung für dieses Problem:
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;
}
Ich hoffe es wird jemandem helfen.