Controller, Formular: Zurück zur newAction und Formularwerte übergeben

  • 0 x
    68 Beiträge
    0 Hilfreiche Beiträge
    11. 11. 2011, 21:07

    Hallo,

    ich überprüfe in der createAction neue Daten aus meinem Anmeldeformular auf einen speziellen Fall (konkret checke ich, ob der gewünschte Benutzername in der verknüpften fe_users schon vorliegt).
    Schlägt die Prüfung fehl, rufe ich die newAction per redirect auf und erhalte mein Formular, inklusive Fehlermeldung (per FlashMessage).
    Aber die Felder sind nun leer, alle Eingaben des Kunden waren also umsonst (bei der eigentlichen Validierung auf Pflichtfelder, passende email etc. werden sie ja wieder mit den berits erfassten Daten ausgefüllt).

    Im arguments-Parameter von redirect($action,$controller,$extension,$arguments) kann ich ja das Object nicht übergeben.
    Und alle Werte per ->getName() an ein Array zu übergeben um das dann wieder per assign in der newAction zu übergeben kann es doch nicht sein?

    newAction:

    1. $this->view->assign('newProvider', $this->request->getArgument('provider'));

    createAction:

    1. $provider['address1'] = $newProvider->getAddress1();
    2. $provider['address1'] = $newProvider->getAddress2();
    3.  
    4. $this->redirect('new','Provider',null,array('provider' => $provider));

    Also: Das funktioniert, aber dann muss ich alle Formular-Felder-Parameter übergeben, was ja fehlerträchtig und wenig erweiterungsfreudig ist...

    Vielleicht hab ich auch was simples übersehen, aber nach diversen Extbase-Problemen und -Grübeleien in dieser Woche raucht mir grade wieder die Birne...

    Viele Grüße vom Rhein, Stefan

  • Hilfreichster Beitrag

  • tpronold tpronold
    TYPO3-Anwärter
    1 x
    6 Beiträge
    1 Hilfreiche Beiträge
    14. 12. 2011, 20:17 - Hilfreichster Beitrag

    hab jetzt nur kurz überflogen, aber eigentlich sollte das doch wunderbar mit forward statt redirect klappen.

    $this->forward('new','Provider',null,array('provider' => $provider));


  • BFSven BFSven
    R2-D2
    0 x
    106 Beiträge
    1 Hilfreiche Beiträge
    14. 11. 2011, 10:53

    Hallo Stefan,

    ich kann Dir kurz beschreiben, wie ich solche Sachen (Formulare + Validierung) angehe.
    Zuerst erstelle ich mir ein Model, das genauso aussieht wie das Formular. In diesem kann ich mit der @validate-Annotation schon mal jede Property für sich testen. Mein Controller hat dann eine indexAction und eine submitAction. Die indexAction zeigt das Formular an, auf die submitAction wird überraschenderweise das Formular geleitet. Schlägt nun eine Validierung fehl, wird automatisch wieder auf die action geleitet, von wo der Aufruf kam, also die indexAction. Um aber nicht in einer Endlos-Validierungsschleife zu enden, muss darüber natürlich mit @dontvalidate $myFormModel die Validierung abgeschaltet werden. Beide Actions bekommen als Paramter (Tx_MyExt_Domain_Model_MyFormModel $myFormModel = NULL). In der indexAction muss das Objekt erzeugt werden, wenn es NULL ist (also der User das erste Mal auf die Seite kommt), und an die View übergeben werden.

    Grau ist alle Theorie, deshalb hier mein Controller:

    1. /**
    2.   * @param Tx_MyExt_Domain_Model_MyForm $myForm
    3.   * @dontvalidate $myForm
    4.   */
    5. public function indexAction(Tx_MyExt_Domain_Model_MyForm $myForm = NULL) {
    6. if ($myForm == NULL) {
    7. $myForm = new Tx_MyExt_Domain_Model_MyForm;
    8. } else {
    9. $formErrors = $this->request->getErrors();
    10. $formErrors = $formErrors['myForm']->getErrors();
    11. $this->view->assign('formErrors', $formErrors);
    12. }
    13. $this->view->assign('myForm', $myForm);
    14. }
    15.  
    16. /**
    17.   * @param Tx_MyExt_Domain_Model_MyForm $myForm
    18.   * @validate $myForm Tx_MyExt_Domain_Model_MyFormValidator
    19.   */
    20. public function submitFormAction(Tx_MyExt_Domain_Model_MyForm $myForm = NULL) {
    21. if($myForm === NULL){
    22. $this->redirect('index');
    23. }
    24. // weitere Bearbeitung
    25. }

    Zusätzlich validiere ich hier noch im Tx_MyExt_Domain_Model_MyFormValidator, um z.B. Abhängigkeiten zwischen Variablen zu validieren. Deine Prüfung, ob ein Name vorhanden ist, könntest Du dann in einem Validator im Model oder im Tx_MyExt_Domain_Model_MyFormValidator durchführen.
    Eine Prüfung nach Gültigkeit von Variablen, bzw. generell Validierung wird nicht im Controller gemacht, denn das ist nicht die Arbeit des Controllers.
    Du musst Dir also keine Gedanken machen wie Deine Daten wieder zur indexAction kommen, das macht Extbase alles für Dich.

    In Deinen Templates benutzt Du dann

    1. <f:form action="submit" object="{myForm}" name="myForm">
    2. <f:form.textbox property="myProp" />
    3. </f:form>

    "name" und "object" muss den gleichen Namen haben.
    Sollte ich was vergessen haben, bitte ich um Hinweise. Vielleicht können wir so Einsteigern die Formular-Verarbeitung leicht näher bringen.

    Beste Grüße,
    Sven

  • 0 x
    68 Beiträge
    0 Hilfreiche Beiträge
    14. 11. 2011, 11:59

    Hallo Sven,

    vielen Dank für Deine ausführliche Antwort.
    Soweit ist es auch klar, das ist ja eigentlich auch das sinnvollste Vorgehen, dafür haben wir ja unsere Objekte und alles andere validiere ich auch dort.

    Mein Problem ensteht ja aber, weil der User zum Login in fe_users seperat angelegt wird.

    Ich erstelle also bei der Anmeldung eines Kunden zum einen einen neuen fe_users-Eintrag (über den ich dann später das ganze Usergruppen und Login-Managment abwickle) und zum anderen einen Eintrag als 'Provider' für den Kundeneintrag.

    Den Providerteil kann ich also nach Extbase-Standard verarbeiten und validieren, aber den Usernamen muss ich ja seperat auf Doppel testetn, da das nicht Teil des Models ist.

    Vielleicht ist mein Kernfehler schon, dass ich nicht fe_users erweitere sondern mit einem eigenen Kunden-Modell operierere. Das schien mir aber wiederum besser zu handeln, wenn es um andere Dinge geht.

    Aber vielleicht muss ich doch von dieser Seite ansetzen?
    Andererseits ist ja nicht das Prüfen und zurückgehen auf die formularaufrufende action das Problem sondern nur, dass ich da nicht mehr (zumindest nicht in der Extbase gerechtwerdenen Eleganz) auf die Feldwerte zugreifen kann.

    Viele Grüße, Stefan

  • alisha alisha
    R2-D2
    0 x
    77 Beiträge
    0 Hilfreiche Beiträge
    06. 12. 2011, 23:53

    Hi,
    ich weiß nicht, ob es noch aktuell ist, aber ich hatte das gleiche Problem und ich lese in der create-Action das POST-Array in ein Array ein und das übergebe ich als Parameter im redirect mit.
    $parameter = array();
    $parameter = t3lib_div::_POST();

    im Formular hole ich mir dann über dieses array die angaben wieder: ..value="{parameter.tx_ext_fe.formularname.name}" ...

    viele Grüße

  • 0 x
    68 Beiträge
    0 Hilfreiche Beiträge
    07. 12. 2011, 05:36

    Hallo,

    das ist ein Weg um wieder an die Daten zu kommen - aber auch hier muss ich wieder alle Felder im Nachhinein anpassen.
    Ich nutze ja wieder nicht die vorhandenen Objektelemente und verlasse damit den Extbaserahmen, oder?

    Aber ich muss zumindest bei Änderungen der Felder diese explizit raussuchen, weil ich alle erreiche - aber habe auch den ganzen POST-Sumpf drin.

    Aber Danke für den Ansatz.

    Viele Grüße, Stefan

  • alisha alisha
    R2-D2
    0 x
    77 Beiträge
    0 Hilfreiche Beiträge
    07. 12. 2011, 10:54

    wenn du eine andere Lösung gefunden hast, das Objekt zu übergeben, kannst du ja posten - würde mich auch interessieren. So rein theoretisch müsste man ja ein Objekt auch serialisieren können und dann in der NewAction daraus wieder ein Objekt erstellen können...

  • alisha alisha
    R2-D2
    0 x
    77 Beiträge
    0 Hilfreiche Beiträge
    14. 12. 2011, 18:31

    Hallo Stefan,
    wie hast du es denn nun gelöst?
    Gruß
    alisha

  • tpronold tpronold
    TYPO3-Anwärter
    1 x
    6 Beiträge
    1 Hilfreiche Beiträge
    14. 12. 2011, 20:17

    hab jetzt nur kurz überflogen, aber eigentlich sollte das doch wunderbar mit forward statt redirect klappen.

    $this->forward('new','Provider',null,array('provider' => $provider));

  • BFSven BFSven
    R2-D2
    0 x
    106 Beiträge
    1 Hilfreiche Beiträge
    15. 12. 2011, 11:07

    Hallo,

    Warum sollte die Übergabe nicht bei redirect klappen?
    Ansonsten haltet Euch an mein Beispiel im 2. Post. Im konkreten Beispiel für Dich Stefan: pack alle Formularelemente in ein Model, welches Du wie oben gezeigt übergibst. Im Tx_MyExt_Domain_Model_MyFormValidator kannst Du dann den Usernamen auch in der fe_users checken. Dies kannst Du machen indem Du ein neues Model/Repository anlegst und fe_users erweiterst oder Du fragst die Tabelle fe_users einfach hart codiert ab (wobei ich ausdrücklich betonen möchte, dass die erste Variante zu bevorzugen ist). Rein theoretisch kannst Du die Validierung auch in einem Tx_MyExt_Domain_Model_UserValidator, welches Du dann per Annotation im Formular-Model an den User bindest, durchführen.
    Gibt es den User(namen) schon, kannst Du im Validator false zurückgeben und es wird - wie vom Framework vorgesehen - zur indexAction zurück-redirected und zwar mit Deinem Formular-Objekt inkl. aller Daten.

    Es muss also niemand für solche Fälle ein redirect (und schon gar kein forward) mit Parametern benutzen, auch für dich alisha, wird es ohne mit Sicherheit auch ohne klappen. Falls Du Fragen hast, poste Deinen Code und wir optimieren das zusammen.

    Beste Grüße, Sven

  • alisha alisha
    R2-D2
    0 x
    77 Beiträge
    0 Hilfreiche Beiträge
    15. 12. 2011, 14:53

    Hallo Sven,
    du hast recht, ich habs auch ohne Parameter hinbekommen. Ich hab zwar kein Formular-Model gemacht, aber mit der newaction und createAction meines normalen Models hat es auch funktioniert. Ich weiß nicht, wo vorher das Problem lag...

    Nun steh ich vor der letzten Hürde:
    In meiner eigenen Validatorklasse möchte ich auf ein Formularwert zugreifen, der nicht zum Model gehört und auch nirgendwo gespeichert werden muss (Bestaetigung der Emailadresse), mit $this->request->getArgument erhalte ich eine Fehlermeldung, vermutlich weil request nur von einer Controller aufgerufen werden kann...
    Muss ich jetzt doch noch so eine Formularmodel-Klasse machen oder gibt es noch eine einfachere Variante?

  • BFSven BFSven
    R2-D2
    0 x
    106 Beiträge
    1 Hilfreiche Beiträge
    15. 12. 2011, 15:09

    Mir fallen jetzt 3 Lösungen ein:
    1. Formular-Model basteln, was die Bestätigung beinhaltet,
    2. Model erweitern (also ne neue Klasse, die von Deiner Klasse ableitet) und als einziges Property die Bestätigung enthält
    3. Versuchen, den POST-Parameter auszulesen

    Dass ich 3. für unsauber halte muss ich bestimmt nicht sagen
    Wenn Du Dein Model nicht ändern kannst, bliebe die 2. Variante. Wenn die Daten dann mit der Oberklasse verarbeitet werden müssen, musst Du halt noch ein Mapping machen.

    Ich selbst würde wohl 1. Variante umsetzen.