Les 6: Formulieren
HomeLes 6

📝 Formulieren

⏱ Geschatte leestijd: 30 minuten · 6 stappen

Symfony Forms maakt het eenvoudig om formulieren te bouwen, in te dienen en te valideren. Je definieert een Form Type-klasse met de velden, koppelt die aan een controller, en toont het formulier in Twig. Validatieregels voeg je toe als Constraints.

1 Hoe werkt een Symfony formulier?

Een Symfony formulier bestaat uit drie onderdelen die samenwerken:

1

Form Type klasse src/Form/ProductType.php

Beschrijft welke velden het formulier heeft, welk type ze zijn (tekst, getal, datum…) en welke validatieregels gelden.

2

Controller src/Controller/...

Maakt het formulier aan, verwerkt de ingediende data en slaat deze op in de database.

3

Twig template templates/...

Toont het formulier als HTML. Symfony genereert de labels, invoervelden en foutmeldingen automatisch.

2 Een Form Type klasse aanmaken

De console genereert een Form Type op basis van een bestaande Entity:

Terminal
# Maak een form type aan voor de Product entity
php bin/console make:form ProductType Product

Dit genereert de volgende klasse, die je daarna aanpast:

src/Form/ProductType.php
<?php

namespace App\Form;

use App\Entity\Product;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;

class ProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            // Tekstveld voor de naam
            ->add('naam', TextType::class, [
                'label' => 'Productnaam',
                'attr'  => ['placeholder' => 'bijv. Laptop Pro'],
                'constraints' => [
                    new Assert\NotBlank(message: 'Vul een naam in.'),
                    new Assert\Length(min: 2, max: 100),
                ],
            ])
            // Geldbedrag voor de prijs
            ->add('prijs', MoneyType::class, [
                'label'    => 'Prijs',
                'currency' => 'EUR',
                'constraints' => [
                    new Assert\NotBlank(message: 'Vul een prijs in.'),
                    new Assert\Positive(message: 'Prijs moet positief zijn.'),
                ],
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        // Koppel dit formulier aan de Product entity
        $resolver->setDefaults(['data_class' => Product::class]);
    }
}

3 Het formulier in de controller

In de controller maak je het formulier aan, verwerk je de POST-data en sla je het object op. Eén methode behandelt zowel GET (toon formulier) als POST (verwerk data).

src/Controller/ProductController.php
use App\Form\ProductType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;

#[Route('/producten/nieuw', name: 'product_nieuw')]
public function nieuw(Request $request, EntityManagerInterface $em): Response
{
    // Maak een leeg Product-object aan
    $product = new Product();

    // Maak het formulier aan en koppel het aan het object
    $form = $this->createForm(ProductType::class, $product);

    // Verwerk de ingediende data (alleen bij POST)
    $form->handleRequest($request);

    // Controleer: is het formulier ingediend én valide?
    if ($form->isSubmitted() && $form->isValid()) {
        // $product heeft nu automatisch de ingevulde waarden
        $em->persist($product);
        $em->flush();

        $this->addFlash('success', 'Product toegevoegd!');
        return $this->redirectToRoute('product_index');
    }

    // Geef het formulier-object door aan de template
    return $this->render('product/nieuw.html.twig', [
        'form' => $form,
    ]);
}

4 Het formulier tonen in Twig

Symfony geeft je handige Twig-functies om het formulier te renderen. Je kunt elk veld apart tonen of alles tegelijk met één regel.

templates/product/nieuw.html.twig — Methode 1: alles tegelijk
{{ form_start(form) }}
    {{ form_widget(form) }}
    <button type="submit" class="btn btn-primary">Opslaan</button>
{{ form_end(form) }}
templates/product/nieuw.html.twig — Methode 2: per veld (meer controle)
{{ form_start(form) }}

    {# form_row toont: label + invoerveld + foutmelding #}
    {{ form_row(form.naam) }}
    {{ form_row(form.prijs) }}

    {# Of nog meer controle: apart renderen #}
    <div class="form-groep">
        {{ form_label(form.naam) }}
        {{ form_widget(form.naam, {'attr': {'class': 'mijn-input'}}) }}
        {{ form_errors(form.naam) }}
    </div>

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

🖥️ Zo ziet het gegenereerde formulier eruit

5 Validatie: constraints instellen

Symfony valideert automatisch op basis van Constraints die je aan de velden koppelt. Als validatie mislukt, worden foutmeldingen getoond — je hoeft zelf geen if-statements te schrijven.

Veelgebruikte constraints — src/Form/ProductType.php
use Symfony\Component\Validator\Constraints as Assert;

// Mag niet leeg zijn
new Assert\NotBlank(message: 'Dit veld is verplicht.')

// Lengte beperken
new Assert\Length(min: 2, max: 255, minMessage: 'Minimaal 2 tekens.')

// Getal moet positief zijn
new Assert\Positive(message: 'Moet een positief getal zijn.')

// Geldig e-mailadres
new Assert\Email(message: 'Vul een geldig e-mailadres in.')

// Minimale leeftijd
new Assert\GreaterThanOrEqual(18, message: 'Moet 18+ zijn.')

// Reguliere expressie
new Assert\Regex(pattern: '/^\d{4}[A-Z]{2}$/', message: 'Ongeldige postcode.')
💡 Tip: Je kunt constraints ook direct op de Entity-eigenschappen zetten (niet in de form). Dan gelden de regels overal waar die Entity gebruikt wordt.

6 Oefenen: bouw een smartphone formulier

Schrijf een SmartphoneType met drie velden: merk (tekst), model (tekst) en prijs (geld). Voeg validatie toe zodat alle velden verplicht zijn.

src/Form/SmartphoneType.php
Klik op "Controleer" om je code te testen...

📋 Samenvatting

  • Een Form Type klasse beschrijft de velden en validatieregels
  • createForm(ProductType::class, $product) maakt het formulier aan in de controller
  • $form->handleRequest($request) verwerkt ingediende data
  • isSubmitted() && isValid() controleert of alles klopt
  • In Twig toon je het formulier met form_start(form), form_row(form.veld) en form_end(form)
  • Constraints regelen validatie: NotBlank, Length, Positive, Email, …
🎓

Gefeliciteerd!

Je hebt alle 6 lessen van SymfonyLearn doorlopen. Je kent nu de basisconcepten van Symfony: installatie, routes, controllers, Twig, Doctrine en formulieren.

Klaar voor de volgende stap? Gebruik je kennis in een echt Symfony-project!

🧠

Kennischeck

Test of je de stof begrepen hebt

Laatste les! Markeer hem als voltooid en voltooi de cursus.