Expert Topics

Wie erstellt man ein einfaches Formular in Symfony 2?

5 Kommentare // Lesezeit: 11 min.

Hinweis: Dieser Artikel ist Teil einer Serie. Der erste Artikel behandelte die Erstellung eines ersten Symfony 2-Projekts.

Es gibt zwei Möglichkeiten, Formulare in Symfony zu erstellen.

  • Der klassische Weg - Erstellung eines Formulars in einer Vorlagendatei
  • Der Symfony-Weg - durch Verwendung von Symfony-Formularen

Welchen Weg soll man nutzen?

Auf den ersten Blick mochte ich Symfony-Formulare nicht besonders, da es sich stark von der klassischen Methode unterscheidet. Die gesamte Formulareinrichtung wird in einer PHP-Klasse vorgenommen, und es respektiert MVC nicht.

Aber Symfony-Formulare können den Erstellungsprozess insbesondere für CRUD-Umgebungen beschleunigen. Ein weiterer Vorteil ist die Unterstützung von Bootstrap seit Symfony 2.6, die Ihnen ein schönes Design in Sekundenschnelle ermöglicht. Symfony-Formulare ist ein großes Feature von Symfony. Sie haben definitiv eine Menge Zeit darin investiert, also muss es gut sein ;)

Also würde ich Symfony Formulare für CRUD-Umgebungen verwenden und wenn es Bedarf für eine Menge von Anpassungen gibt, würde ich es auf "klassische" Weise machen. Aber denken Sie daran, dass Symfony2 Formulare bieten eine Menge von Anpassungsmöglichkeiten, die für Ihre Bedürfnisse ausreichend sein könnte.

Symfony-Formular mit many-to-many-Beziehung

Ich werde die Erstellung eines Symfony-Formulars mit einer N-zu-N-Beziehung anhand des Beispiels Benutzer - Rollen demonstrieren, nur dass in meinem Beispiel die Benutzerklasse Employee heißt. Viele Angestellte können dieselbe Rolle haben und viele Rollen können einem Angestellten zugewiesen werden, deshalb ist es eine viele zu viele Beziehung. In den nächsten Zeilen zeige ich Ihnen, wie Sie ein Symfony2-Formular erstellen, das die Bearbeitung der Entität Employee erlaubt und das Hinzufügen vieler Rollen zu unserem Mitarbeiter ermöglicht.

1. Erstellen Sie die employee Entität

Dies kann über den einfachen Konsolenbefehl erfolgen, der die Entität im interaktiven Modus erzeugt. Die Konsole fragt nach dem Namen der Entität und nach dem Namen und Typ jedes Feldes.

php app/console doctrine:generate:entity

Am Ende sollten Sie eine Klasse wie diese erhalten:

Die Employee-Klasse erweitert die Person-Klasse, die Felder und deren Getter und Setter wie firstName, lastName, email, activeFrom, activeTo, ID enthält. Diese beiden Entitäten werden durch die Vererbung von Klassentabellen abgebildet, die nicht Gegenstand dieses Beitrags ist, daher werde ich sie jetzt nicht erklären. Für uns ist das Wichtigste in dieser Klasse das Feld $roles, das eine Seite der many-to-many-Beziehung darstellt.

2. Erstellen Sie die role Entität


Braucht Ihr Unternehmen einen Webspezialisten, mit dem es auf Augenhöhe sprechen kann?

 


3. Implementierung des Symfony Formulares

Es ist möglich, Symfony-Formular innerhalb einer Controller-Aktion zu definieren, aber es ist schlechte Praxis, zu viel Zeug in Controllern zu setzen. Der beste Weg ist, ein Formular in einer separaten Datei zu erstellen. Um einen Anfang zu haben, können Sie diesen Befehl verwenden:

php app/console doctrine:generate:form AppBundle:Employee --no-interaction

Wie Sie sehen können, hat diese Klasse 3 Methoden. Die wichtigste ist die buildForm-Methode, denn hier wird jedes Formularelement durch den Aufruf der $builder->add-Methode zum Formular hinzugefügt. Das erste Argument muss ein String sein - der Name des Feldes, und es muss der exakte Name sein, wie er in der Entität steht. Außerdem muss es eine entsprechende Getter-Funktion haben. Das zweite Argument ist ein Feldtyp. Das dritte und letzte Argument (nicht erforderlich) ist ein Array von Einstellungen für das Formularelement. Wie Sie sehen können, benötigte ich keine Einstellungen für das Feld firstName.

Zum Beispiel wird $builder->add('firstName', 'text') die Beschriftung 'Vorname' und rechts davon das Eingabetextfeld darstellen. Wenn Sie die Beschriftung ändern möchten, können Sie dies tun, indem Sie 'label' => 'Custom label name' zum Array settings hinzufügen. Analysieren wir unsere Definition des Formularelements für die Many-to-many-Beziehung Zeile für Zeile:

'rolesCollection', 'entity', - Sie haben vielleicht bemerkt, dass meine Entität Employee kein rolesCollection-Feld hat, aber sie hat einen entsprechenden Getter (public function getRolesCollection()), der das Feld $roles zurückgibt, wie es ist (ArrayCollection), und nur das ist für uns wichtig. Ich musste den ursprünglichen Getter (public function getRoles()) so ändern, dass er ein Array von Rollennamen für den Authentifizierungsprozess zurückgibt, daher konnte ich diesen Getter hier nicht verwenden. Und es ist wichtig, 'entity' als zweites Argument zu wählen.

'class' => 'AppBundle\Entity\Role', - gezielte Entitätsklasse
'property' => 'name', - Eigenschaft der anzuzeigenden Rolle. Diese Option ist nicht erforderlich, wenn die Zielentität über die Methode __toString() verfügt, die beim Rendern jeder Rolle in diesem Formular aufgerufen würde
'multiple' => TRUE, - sagt, dass es möglich ist, mehrere Felder auszuwählen.
'expanded' => TRUE, - wenn TRUE, werden alle Rollen je nach dem Attribut 'multiple' als Kontrollkästchen oder Optionsfelder dargestellt, wenn FALSE, werden die Rollen je nach dem Attribut 'multiple' in einer Dropdown-Liste oder in einer Mehrfachauswahlliste dargestellt.
'label' => 'Roles', - wie erklärt, benutzerdefiniertes Label
'disabled' => !$this->loggedInUser->isAdmin(), - wenn TRUE, wird das Eingabeelement deaktiviert.

Sehen wir uns an, wie das role Element in Abhängigkeit von "mehreren" und "erweiterten" Feldern aussehen wird:

'multiple' => TRUE,
'expanded' => TRUE,

'multiple' => TRUE,
'expanded' => FALSE,

'multiple' => FALSE,
'expanded' => TRUE,

'multiple' => FALSE,
'expanded' => FALSE,

In der Methode getName() legen wir den Namen unseres Formulartyps fest. Dieser Name sollte in der gesamten Anwendung eindeutig sein. In der Methode configureOptions() habe ich Symfony mitgeteilt, wie der vollständige Name der Entitätsklasse lautet, die hinter diesem Formular steht. Symfony kann den Klassennamen automatisch herausfinden, aber es ist gute Praxis, ihn hier zu definieren.

Ich möchte nur erwähnen, dass das Feld $loggedInUser für die Funktion des Formulars nicht wichtig ist. Ich verwende es nur, um festzustellen, ob der aktuell angemeldete Benutzer ein Administrator ist, damit ich das Formular entsprechend rendern kann.

Validierung von Formularen

Die Backend-Validierung des Formulars erfolgt auf der Grundlage von Einschränkungen, die in Entitäten definiert sind. Wenn wir z.B. ein Pflichtfeld erstellen wollen, müssen wir nur diese Anmerkung in der Entität über dem Feld hinzufügen: @Assert\NotBlank().

Dieses E-Mail-Feld ist also erforderlich, es wird validiert, wenn es eine E-Mail ist, und es muss eindeutig sein, da es nicht löschbar ist. Wenn es Validierungsfehler gibt, landet der Benutzer beim Absenden des Formulars auf einer Formularseite mit einer Fehlermeldung neben dem ungültigen Feld. All das wird automatisch von Symfony erledigt.

4. Durchführung der Controller-Aktion

Ich verwende dieselbe Methode für das Hinzufügen neuer Mitarbeiter und für die Bearbeitung bestehender Mitarbeiter. Lassen Sie uns nur über die Bearbeitung eines Mitarbeiters sprechen. Diese Aktion hat 3 Ergebnisse:

1. Benutzer hat auf den Bearbeitungslink in der employee Tabelle geklickt

Diese Aktion wird mit der employee-ID aufgerufen. Der Mitarbeiter wird aus der Datenbank geholt, so dass wir in den Formularfeldern die aktuellen Werte der Mitarbeiterfelder sehen können. Jetzt kommt der wichtigste Teil - das Formular wird aus unserem Typ erstellt:
$form = $this->createForm(new EmployeeType($loggedInUser), $employee);

Als Nächstes kommt die Bearbeitung der Anfrage, aber da wir das Formular nicht abgeschickt haben, gibt $form->isValid() FALSE zurück, und die Vorlage für die Bearbeitung von Mitarbeitern wird mit dem Formular und den ursprünglichen Feldwerten gerendert.

2. Der Benutzer hat das Formular abgeschickt und es ist gültig

Nach der Bearbeitung der Anfrage ($form->handleRequest($request)) werden alle in die Formularfelder eingegebenen Werte in das Objekt $employee übernommen. Da das Formular gültig ist, werden wir den if-Block eingeben:

Das Mitarbeiterobjekt mit den neuen Werten wird in der Datenbank gespeichert und wir werden zur Listenseite weitergeleitet.

3. Der Benutzer hat das Formular abgeschickt und es ist ungültig

Wenn das Formular ungültig ist, werden wir den if-Block nicht eingeben und die Bearbeitungsseite mit dem Formular wird mit Fehlermeldungen angezeigt.

5. Verwirklichung der Vorlagen

Da Symfony Forms die ganze Arbeit für uns erledigt hat, einschließlich der Validierung von Frontend und Backend, müssen wir nur noch das Formular zur Twig-Datei hinzufügen. Dies ist der einfachste Weg:

Wenn es erforderlich ist, die Elemente anzupassen und zu gestalten, kann jedes Element separat in die Twig-Datei eingefügt werden.

6. Styling

Wir wollen nicht zu viel Zeit mit dem Styling verbringen, also verwenden wir das Bootstrap-Theme. Wir müssen es nur in der Datei config.yml aktivieren:

Und so sieht unser Formular aus:

Unglaublich, nicht wahr? :D

Kontaktieren Sie uns!

Wir sind eine Digitalagentur, die sich auf die Entwicklung digitaler Produkte spezialisiert hat. Unsere Kernthemen sind Webseiten und Portale mit TYPO3, eCommerce mit Shopware und Android und iOS-Apps. Daneben beschäftigen wir uns mit vielen weiteren Themen im Bereich Webentwicklung. Kontaktieren Sie uns gerne mit Ihren Anliegen!

Kommentare

  • Cedric Ziel

    Cedric Ziel

    am 28.07.2015

    I'd be interested in the reason why you claim forms act contrary to your specific definition/interpretation of MVC as you claimed at the beginning. Could you go a little more in detail upon that? [...] I'd be interested in the reason why you claim forms act contrary to your specific definition/interpretation of MVC as you claimed at the beginning. Could you go a little more in detail upon that? Maybe even what you consider to be the classical way you mentioned in a sidenote.

    Thx a lot,
    Cedric

  • Damjan

    Damjan

    am 28.07.2015

    Hi Cedric. Thanks for the comment.

    When I say "classical way" I think on making a form in a template file, by using twig or HTML elements.
    MVC architecture dictates clear separation of [...] Hi Cedric. Thanks for the comment.

    When I say "classical way" I think on making a form in a template file, by using twig or HTML elements.
    MVC architecture dictates clear separation of model, view and control layers in a web application, and for me, that separation is not so clear in the case of Symfony forms. Since we define form fields and its attributes in a Type class (e.g. EmployeeType), it is part of the view layer. And yet Symfony forms also do the model manipulation, which is job of the control layer.

    -Damjan

  • Sam

    Sam

    am 13.06.2016

    Hi Mr. Damjan. Your Guide is very useful especially for us (newbies). I like your guide, it's simple and clean. I tried doing the same form, the same strategy, but i only included the part where i am [...] Hi Mr. Damjan. Your Guide is very useful especially for us (newbies). I like your guide, it's simple and clean. I tried doing the same form, the same strategy, but i only included the part where i am displaying a Dropdown where a user has to choose only one record and Checkboxes where a user could check as many as he/she wants. The field for the categories and checkboxes are taken from another entity. But i have a question about the project I am currently developing. The dropdowns and checkboxes shows up but when i try to submit it, it throws an error "Found entity of type Doctrine\Common\Collections\ArrayCollection on association SampleProj\CheckBundle\Entity\Dropdown#parameter, but expecting SampleProj\CheckBundle\Entity\Parameters.

    P.S. I used ManyToOne Relationship for the two entities (category, parameter).

  • Boris

    Boris

    am 29.07.2017

    Old version of Symfony, but still helpful :-) Thank for your article. Old version of Symfony, but still helpful :-) Thank for your article.

  • Ketan Chavda

    Ketan Chavda

    am 04.09.2017

    Its really good article for beginners as well as experienced.
    Its really short and sweet explanation.
    Thanks for this good article. Its really good article for beginners as well as experienced.
    Its really short and sweet explanation.
    Thanks for this good article.