In Symfony gibt es bekanntlich den sehr mächtigen FormBuilder. Manchmal genügt ein
1 2 3 4 |
$form = $this->createFormBuilder($user) ->add('password', RepeatedType::class, ['type' => PasswordType::class]) ->add('send', SubmitType::class) ->getForm(); |
und wir haben ein Formular für eine Passwortänderung.
Spannend wird es aber natürlich erst, wenn wir unseren eigenen FormType definieren und damit ein komplexeres Formular aufbauen. In diesem Artikel geht es dabei um die Problematik einer benutzerdefinierten Option.
Grundgerüst des eigenen FormType
Für ein eigenes Formular benötigen wir lediglich eine Klasse, die von Symfony\Component\Form\AbstractType
erbt und die Methode buildForm()
implementiert.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; class EditEmail extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('key', TextType::class, ['label' => 'Key']) ->add('subject', TextType::class, ['label' => 'Betreff']) ->add('content', TextareaType::class, ['label' => 'Nachricht']) ->add('send', SubmitType::class, ['label' => 'Speichern']); } } |
Eigene Optionen hinzufügen
Obiges Formular definiert unabhängig von äußeren Bedingungen ein Formular. So weit so gut. Ab und an benötigen wir aber ein dynamisches Verhalten, dass der Controller festlegen kann.
Wir erweitern unser Formular als mit einer Option.
1 2 3 4 5 6 7 8 9 10 |
public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('key', TextType::class, ['label' => 'Key']) ->add('subject', TextType::class, [ 'label' => 'Betreff', 'attr' => ['readonly' => $options['disableSubject']], ]) ->add('content', TextareaType::class, ['label' => 'Nachricht']) ->add('send', SubmitType::class, ['label' => 'Speichern']); } |
Der Controller soll also bestimmen können, ob der Betreff bearbeitet werden darf, oder nicht.
Wir erstellen das Formular also mit der entsprechenden Option:
1 |
$form = $this->createForm(EditEmail::class, $template, ['disableSubject' => true]); |
Genau hier wirft uns aber Symfony eine Exception um die Ohren:
The option „disableSubject“ does not exist. Defined options are: …
Standardwert zur Rettung
Das Prinzip hinter der Mechanik an dieser Stelle ist, dass das Formular immer ohne jegliche Optionen verwendet werden kann. Es ist also notwendig, dass alle Optionen eine Standardwert erhalten.
Diesen können wir in der Methode configureOptions()
festlegen.
1 2 3 4 5 6 7 8 9 10 |
public function configureOptions(OptionsResolver $resolver) { parent::configureOptions($resolver); $resolver->setDefaults([ 'data_class' => 'EmailTemplate', 'validation_groups' => ['edit'], 'disableSubject' => false, ]); } |
Damit ist diese Option bekannt. Obige Exception würde sie jetzt ebenfalls auflisten, falls wir mal einen Tippfehler machen.
Unser Formular verhält sich jetzt wie wir es erwarten und wir können vom Controller aus diese benutzerdefinierte Option nutzen, oder weglassen und den Standardwert verwenden.