Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Formulare mit Symfony Forms erstellen

Formulare mit Symfony Forms erstellen

~16 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Symfony Forms ist EINES der mächtigsten Bündel dieses Frameworks: aus EINER PHP-Klasse entstehen automatisch HTML-Formular, serverseitige Verarbeitung UND Validierung (Kapitel 16) – DREI Aufgaben aus einer einzigen Quelle.

Einen Form Type generieren

php bin/console make:form ProjectType

make:form (aus dem maker-bundle, Kapitel 6) erzeugt ein Grundgerüst unter src/Form/ – wir passen es für unser Projekt an. (Da unsere Entity-Klassen erst in Block 4 entstehen, arbeiten wir vorerst OHNE die data_class-Option und geben stattdessen ein Array zurück.)

src/Form/ProjectType.php
<?php

declare(strict_types=1);

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;

class ProjectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name', TextType::class, [
                'label' => 'Projektname',
            ])
            ->add('beschreibung', TextareaType::class, [
                'label' => 'Beschreibung',
                'required' => false,
            ])
        ;
    }
}

Den Form Type im Controller nutzen

src/Controller/ProjectController.php
use App\Form\ProjectType;

#[Route('/projects/new', name: 'project_new', methods: ['GET', 'POST'])]
public function new(Request $request): Response
{
    $form = $this->createForm(ProjectType::class);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $daten = $form->getData();
        // $daten['name'] und $daten['beschreibung'] enthalten die eingegebenen Werte

        $this->addFlash('success', 'Projekt erfolgreich erstellt!');
        return $this->redirectToRoute('project_index');
    }

    return $this->render('project/new.html.twig', [
        'form' => $form,
    ]);
}

handleRequest($request) ist der entscheidende Aufruf: bei einem GET-Request bleibt das Formular UNBEFÜLLT, bei einem POST-Request liest es AUTOMATISCH $request->request (Kapitel 10) aus und befüllt das Formular-Objekt – wir müssen NICHT mehr manuell auf einzelne POST-Felder zugreifen.

isSubmitted() prüft, ob überhaupt Daten gesendet wurden (also POST statt GET), isValid() prüft die Validierung – Kapitel 16 fügt echte Validierungsregeln hinzu, OHNE die auch leere Felder aktuell als "valide" gelten.

Das Formular in Twig rendern

templates/project/new.html.twig
{% extends 'base.html.twig' %}

{% block body %}
    <h1>Neues Projekt</h1>

    {{ form(form) }}
{% endblock %}

{{ form(form) }} rendert das KOMPLETTE Formular – ALLE Felder, Labels, Validierungsfehler UND einen Submit-Button, inklusive <form>-Tag und CSRF-Schutz (Kapitel 18) – mit EINER einzigen Twig-Funktion.

Feingranulares Rendering für individuelles Styling

form(form) ist praktisch für den Einstieg, aber im echten Projekt braucht man meist mehr Kontrolle über das HTML-Markup:

{{ form_start(form) }}
    <div class="formular-feld">
        {{ form_label(form.name) }}
        {{ form_widget(form.name) }}
        {{ form_errors(form.name) }}
    </div>

    <div class="formular-feld">
        {{ form_row(form.beschreibung) }}
    </div>

    <button type="submit">Speichern</button>
{{ form_end(form) }}

form_row(...) bündelt Label, Widget und Fehler für EIN Feld (wie beim beschreibung-Feld oben) – der Mittelweg zwischen der Alles-oder-nichts-Funktion form(form) und der vollständig manuellen Kontrolle über form_label/form_widget/form_errors einzeln (wie beim name-Feld).

Tipp: Faustregel: form(form) für schnelle Prototypen und interne Tools, form_row() pro Feld für die meisten Produktions-Formulare, einzelne form_label/form_widget/form_errors-Aufrufe nur für WIRKLICH individuell gestaltete Felder.