Il contesto
Nel pannello di admin di baccalaureat.sn, gestisco i log di download delle annate. Volevo mostrare due colonne che non corrispondono a nessuna proprietà mappata dell'entità: l'etichetta leggibile della prova e un badge premium.
Il sintomo
public function configureFields(string $pageName): iterable
{
    yield TextField::new('epreuveLabel', 'Épreuve');
    yield TextField::new('isPremium', 'Premium');
}
Risultato: colonne vuote, oppure eccezione Neither the property "epreuveLabel" nor one of the methods ... exist.
Perché si rompe
EasyAdmin parte dal presupposto che un Field corrisponda a una proprietà accessibile tramite PropertyAccess. Per un campo che non esiste sull'entità, bisogna dichiararlo virtuale.
La soluzione
yield TextField::new('epreuveLabel', 'Épreuve')
    ->setVirtual(true)
    ->formatValue(fn ($value, $entity) => sprintf(
        '%s — %s (%s)',
        $entity->getMatiere(),
        $entity->getSerie(),
        $entity->getAnnee()
    ));
Per un rendering HTML, un template dedicato:
yield TextField::new('isPremium', 'Premium')
    ->setVirtual(true)
    ->setTemplatePath('admin/field/premium_badge.html.twig');
{# templates/admin/field/premium_badge.html.twig #}
{% if entity.instance.account and entity.instance.account.isPremium %}
    Premium
{% else %}
    Gratuit
{% endif %}
Punto che mi è costato un'ora: in un template di campo EasyAdmin, l'entità reale è sotto entity.instance, non entity.
Cosa mi porto a casa
  • setVirtual(true) non appena un campo non corrisponde a una proprietà Doctrine.
  • formatValue() riceve ($value, $entity) — comodo per comporre un valore.
  • Nei template di campo: entity.instance per l'oggetto.