Skip to Content
SymfonyPartie 16 — Annexes16.4 — Cheatsheet Doctrine & Twig

16.4 — Cheatsheet Doctrine & Twig

Doctrine — mapping (attributs)

#[ORM\Entity(repositoryClass: BookingRepository::class)] #[ORM\Table(name: 'bookings')] #[ORM\Index(columns: ['status'])] class Booking { #[ORM\Id, ORM\GeneratedValue, ORM\Column] private ?int $id = null; #[ORM\Column(length: 255)] private string $email; #[ORM\Column(type: 'decimal', precision: 10, scale: 2, nullable: true)] private ?string $amount = null; #[ORM\Column(enumType: BookingStatus::class)] private BookingStatus $status = BookingStatus::Pending; }

Doctrine — relations

// ManyToOne (côté propriétaire, porte la FK) #[ORM\ManyToOne(inversedBy: 'bookings')] #[ORM\JoinColumn(nullable: false)] private ?User $user = null; // OneToMany (côté inverse) /** @var Collection<int, Booking> */ #[ORM\OneToMany(targetEntity: Booking::class, mappedBy: 'user', orphanRemoval: true)] private Collection $bookings; // new ArrayCollection() dans le constructeur // ManyToMany #[ORM\ManyToMany(targetEntity: Tag::class, inversedBy: 'services')] private Collection $tags; // OneToOne #[ORM\OneToOne(inversedBy: 'payment')] private ?Booking $booking = null;

Doctrine — persistance & requêtes

$em->persist($entity); $em->flush(); // insert (un seul flush) $entity->setX(...); $em->flush(); // update (Unit of Work détecte) $em->remove($entity); $em->flush(); // delete // Repository (méthodes de base) $repo->find(42); $repo->findBy(['status' => X], ['start' => 'ASC'], 20); $repo->findOneBy(['email' => $e]); $repo->count(['status' => X]); // QueryBuilder (+ fetch join anti N+1) $this->createQueryBuilder('b') ->addSelect('s')->join('b.slot', 's') // charge la relation ->andWhere('b.status = :s')->setParameter('s', $status) // JAMAIS de concat ->orderBy('b.start', 'DESC') ->setFirstResult(($page-1)*$per)->setMaxResults($per) ->getQuery()->getResult(); // Résultats ->getResult(); // Entity[] ->getOneOrNullResult(); // Entity|null ->getSingleScalarResult(); // COUNT / scalaire ->toIterable(); // générateur (gros volumes)

Twig — syntaxe

{# affichage / logique / commentaire #} {{ variable }} {% if x %}...{% endif %} {# note #} {# accès #} {{ booking.customerEmail }} {# clé, propriété OU getter #} {{ booking.status.label }} {# méthode d'enum #} {# filtres #} {{ name|upper }} {{ date|date('d/m/Y H:i') }} {{ x|default('—') }} {{ items|length }} {{ price|number_format(2, ',', ' ') }} {# fonctions #} {{ path('route', { id: x }) }} {{ asset('img.png') }} {{ is_granted('EDIT', obj) }} {# conditions / boucles #} {% for slot in service.slots %} {{ loop.index }} — {{ slot.start|date('H:i') }} {% else %} Aucun créneau. {% endfor %} {# héritage #} {% extends 'base.html.twig' %} {% block body %}...{{ parent() }}...{% endblock %} {# include / composant #} {% include 'partials/_row.html.twig' with { booking: b } only %} <twig:StatusBadge :status="booking.status" /> {# global app #} {{ app.user.email }} {{ app.request.locale }} {{ app.flashes }}

Formulaire (Twig)

{{ form_start(form) }} {{ form_row(form.email) }} {{ form_widget(form.seats) }} {{ form_errors(form.seats) }} {{ form_rest(form) }} {# n'oubliez pas : rend le token CSRF #} {{ form_end(form) }}

Suivant : 16.5 — Pièges & FAQ.