📋 Cheatsheet
📋 Symfony Cheatsheet
Klik een rij om het codevoorbeeld uit te klappen · Kopieer met de knop
🔍
Niets gevonden
⚡ Symfony CLI & Composer
composer create-project symfony/skeleton naam
Nieuw project aanmaken
Maakt een nieuw Symfony-project aan in een map met de opgegeven naam.
composer create-project symfony/skeleton mijn-app
cd mijn-app
php -S localhost:8000 -t public/
php bin/console cache:clear
Cache leegmaken
Verwijdert de gecachete bestanden in var/cache/. Nodig na het aanpassen van routes of configuratie.
php bin/console cache:clear
# Of voor productieomgeving:
php bin/console cache:clear --env=prod
php bin/console make:controller NaamController
Controller aanmaken
Genereert automatisch een controller-klasse en bijbehorend Twig-template.
php bin/console make:controller ProductController
# Maakt aan:
# src/Controller/ProductController.php
# templates/product/index.html.twig
php bin/console make:entity Naam
Entity aanmaken
Start een interactieve wizard voor het aanmaken van een Entity met velden en types.
php bin/console make:entity Product
# Daarna: veldnaam, type (string/int/etc), lengte, nullable
# Maakt aan: src/Entity/Product.php + src/Repository/ProductRepository.php
php bin/console make:migration
Migratie aanmaken
php bin/console make:migration # Migratie aanmaken
php bin/console doctrine:migrations:migrate # Migratie uitvoeren
php bin/console doctrine:migrations:status # Status bekijken
php bin/console debug:router
Alle routes tonen
php bin/console debug:router # Alle routes tonen
php bin/console debug:router app_home # Specifieke route tonen
php bin/console debug:container # Alle services tonen
composer require [pakket]
Pakket installeren
composer require twig # Twig templates
composer require doctrine orm # Database ORM
composer require form validator # Formulieren
composer require security-bundle # Authenticatie
composer require mailer # E-mail verzenden
composer require webapp # Alles voor een volledige app
🗺️ Routes
#[Route('/pad', name: 'naam')]
Basis route
use Symfony\Component\Routing\Attribute\Route;
class HomeController extends AbstractController
{
#[Route('/', name: 'app_home')]
public function index(): Response
{
return $this->render('home/index.html.twig');
}
}
#[Route('/product/{id}')]
Route met parameter
#[Route('/product/{id}', name: 'product_show')]
public function show(int $id): Response
{
// $id is automatisch beschikbaar als argument
return $this->render('product/show.html.twig', ['id' => $id]);
}
// Meerdere parameters:
#[Route('/blog/{categorie}/{slug}', name: 'blog_show')]
public function blogShow(string $categorie, string $slug): Response { ... }
requirements: ['id' => '\d+']
Parameter beperken
// Alleen cijfers toegestaan voor {id}
#[Route('/product/{id}', name: 'product_show', requirements: ['id' => '\d+'])]
// Alleen letters voor {slug}
#[Route('/blog/{slug}', requirements: ['slug' => '[a-z0-9\-]+'])]
methods: ['GET', 'POST']
HTTP methoden
#[Route('/verwerk', name: 'verwerk', methods: ['POST'])]
public function verwerk(): Response { ... }
// Meerdere methoden:
#[Route('/item', name: 'item', methods: ['GET', 'POST'])]
$this->generateUrl('naam', ['id' => 5])
URL genereren
// In een controller:
$url = $this->generateUrl('product_show', ['id' => 5]);
// → "/product/5"
// In Twig:
// {{ path('product_show', {id: 5}) }}
// {{ url('product_show', {id: 5}) }} ← absolute URL
🎮 Controllers
class … extends AbstractController
Basis controller
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class ProductController extends AbstractController
{
#[Route('/producten', name: 'product_index')]
public function index(): Response
{
return $this->render('product/index.html.twig', [
'title' => 'Alle producten',
]);
}
}
return $this->render('template.html.twig', $data)
Template renderen
return $this->render('product/index.html.twig', [
'producten' => $producten, // beschikbaar als {{ producten }} in Twig
'titel' => 'Overzicht',
]);
return $this->redirectToRoute('naam')
Redirect
// Eenvoudige redirect:
return $this->redirectToRoute('product_index');
// Met parameters:
return $this->redirectToRoute('product_show', ['id' => $product->getId()]);
// Externe URL redirect:
return $this->redirect('https://symfony.com');
return $this->json(['key' => 'value'])
JSON response
return $this->json([
'status' => 'ok',
'data' => $producten, // arrays en objecten worden automatisch geserialiseerd
]);
// Geeft Content-Type: application/json terug
$request->get('naam')
Request data lezen
use Symfony\Component\HttpFoundation\Request;
public function opslaan(Request $request): Response
{
$naam = $request->get('naam'); // GET of POST
$pagina = $request->query->get('pagina', 1); // ?pagina=2
$veld = $request->request->get('veld'); // POST body
$isPost = $request->isMethod('POST'); // boolean
}
throw $this->createNotFoundException()
404 fout gooien
$product = $repository->find($id);
if (!$product) {
throw $this->createNotFoundException('Product niet gevonden');
}
// Symfony toont automatisch de 404-pagina
🌿 Twig Templates
{{ variabele }}
Variabele tonen
{{ naam }} {# Eenvoudige variabele #}
{{ product.naam }} {# Property van een object #}
{{ producten[0] }} {# Eerste element van array #}
{{ naam|upper }} {# Filter: HOOFDLETTERS #}
{{ naam|lower }} {# filter: kleine letters #}
{{ naam|length }} {# Aantal tekens #}
{{ prijs|number_format(2, ',', '.') }} {# 1.234,56 #}
{{ datum|date('d-m-Y') }}
Datum formatteren
{{ datum|date('d-m-Y') }} {# 18-05-2026 #}
{{ datum|date('d F Y') }} {# 18 May 2026 #}
{{ datum|date('H:i') }} {# 14:30 #}
{{ 'now'|date('Y') }} {# Huidig jaar #}
{% if conditie %}…{% endif %}
If statement
{% if leeftijd >= 18 %}
Volwassen
{% elseif leeftijd >= 12 %}
Tiener
{% else %}
Kind
{% endif %}
{% if producten is empty %}
Geen producten gevonden.
{% endif %}
{% if gebruiker is defined and gebruiker %}
Welkom, {{ gebruiker.naam }}!
{% endif %}
{% for item in items %}…{% endfor %}
For loop
{% for product in producten %}
{{ loop.index }}. {{ product.naam }}
{% else %}
Geen producten gevonden.
{% endfor %}
{# Loop variabelen: #}
{# loop.index → 1, 2, 3, … #}
{# loop.index0 → 0, 1, 2, … #}
{# loop.first → true bij eerste item #}
{# loop.last → true bij laatste item #}
{# loop.length → totaal aantal items #}
{% extends 'base.html.twig' %}
Template overerving
{# base.html.twig #}
<!DOCTYPE html>
<html>
<body>
{% block content %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
{# product/index.html.twig #}
{% extends 'base.html.twig' %}
{% block content %}
<h1>Producten</h1>
{% endblock %}
{% include %} · {% set %} · path()
Diversen
{% include 'partials/_nav.html.twig' %}
{% include 'card.html.twig' with {product: item} %}
{% set totaal = prijs * aantal %}
{% set bericht = 'Hallo ' ~ naam %}
{{ path('product_show', {id: product.id}) }}
{{ asset('css/style.css') }}
🗄️ Doctrine ORM
#[ORM\Entity] · #[ORM\Column]
Entity definitie
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $naam = null;
#[ORM\Column(type: 'float')]
private ?float $prijs = null;
#[ORM\Column(type: 'boolean')]
private bool $actief = true;
// Getters en setters...
}
$em->persist($obj); $em->flush();
Data opslaan
use Doctrine\ORM\EntityManagerInterface;
class ProductController extends AbstractController
{
public function __construct(
private EntityManagerInterface $em
) {}
public function nieuw(): Response
{
$product = new Product();
$product->setNaam('Laptop');
$product->setPrijs(999.95);
$this->em->persist($product); // registreren
$this->em->flush(); // SQL INSERT uitvoeren
return $this->redirectToRoute('product_index');
}
public function update(Product $product): Response
{
$product->setPrijs(899.00); // alleen wijzigen
$this->em->flush(); // SQL UPDATE uitvoeren
// Geen persist() nodig voor bestaand object!
}
}
findAll() · find($id) · findBy([])
Data ophalen
$repo = $this->em->getRepository(Product::class);
$all = $repo->findAll(); // alle rijen
$one = $repo->find(5); // op id
$active = $repo->findBy(['actief' => true]); // gefilterd
$sorted = $repo->findBy(['actief' => true], ['naam' => 'ASC']); // gesorteerd
$eerste = $repo->findOneBy(['naam' => 'Laptop']); // één resultaat
// Via autowiring (aanbevolen):
class ProductController extends AbstractController
{
public function __construct(
private ProductRepository $repo
) {}
}
createQueryBuilder('p')->where(…)
QueryBuilder
// In een Repository-methode:
public function findGoedkoop(float $max): array
{
return $this->createQueryBuilder('p')
->andWhere('p.prijs < :max')
->setParameter('max', $max)
->orderBy('p.prijs', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult();
}
#[ORM\ManyToOne] · #[ORM\OneToMany]
Relaties
// Product behoort tot één Category (many products → one category)
#[ORM\ManyToOne(targetEntity: Category::class)]
#[ORM\JoinColumn(nullable: false)]
private ?Category $category = null;
// Category heeft meerdere Products (one category → many products)
#[ORM\OneToMany(mappedBy: 'category', targetEntity: Product::class)]
private Collection $products;
// In Twig:
// {{ product.category.naam }}
// {% for p in category.products %}{{ p.naam }}{% endfor %}
📝 Formulieren
class NaamType extends AbstractType
FormType aanmaken
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('naam', TextType::class, ['label' => 'Productnaam'])
->add('email', EmailType::class, ['label' => 'E-mail'])
->add('opslaan', SubmitType::class, ['label' => 'Opslaan']);
}
}
handleRequest · isSubmitted · isValid
Formulier verwerken
public function nieuw(Request $request): Response
{
$product = new Product();
$form = $this->createForm(ProductType::class, $product);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// $product is nu gevuld met formulierdata
$this->em->persist($product);
$this->em->flush();
$this->addFlash('success', 'Opgeslagen!');
return $this->redirectToRoute('product_index');
}
return $this->render('product/nieuw.html.twig', [
'form' => $form,
]);
}
#[Assert\NotBlank] · #[Assert\Email]
Validatie constraints
use Symfony\Component\Validator\Constraints as Assert;
class Product
{
#[Assert\NotBlank(message: 'Vul een naam in')]
#[Assert\Length(min: 2, max: 100)]
private ?string $naam = null;
#[Assert\Email]
#[Assert\NotBlank]
private ?string $email = null;
#[Assert\Range(min: 0, max: 99999)]
#[Assert\NotNull]
private ?float $prijs = null;
#[Assert\Regex(pattern: '/^[a-z0-9]+$/', message: 'Alleen kleine letters en cijfers')]
private ?string $slug = null;
}
form_start · form_row · form_end
Formulier in Twig
{{ form_start(form) }}
{{ form_row(form.naam) }} {# label + input + fout #}
{{ form_row(form.email) }}
{{ form_row(form.opslaan) }}
{{ form_end(form) }} {# sluit form + CSRF token #}
{# Of alles in één: #}
{{ form(form) }}
{# Foutmeldingen tonen: #}
{{ form_errors(form) }}
{{ form_errors(form.naam) }} {# veld-specifiek #}
$this->addFlash('success', '…')
Flash messages
// In controller (na redirect):
$this->addFlash('success', 'Product opgeslagen!');
$this->addFlash('error', 'Er ging iets mis.');
return $this->redirectToRoute('product_index');
{# In Twig (base.html.twig): #}
{% for type, messages in app.flashes %}
{% for message in messages %}
<div class="flash flash-{{ type }}">{{ message }}</div>
{% endfor %}
{% endfor %}
SymfonyLearn · Cheatsheet · Officiële documentatie →