Matti Mäkitalo: Formulardaten in mehrseitigen Formularen übertragen

Hi,

ich würde gerne etwas über eure Ideen erfahren, wie ihr folgendes Problem löst.

Ich habe einen Workflow, welcher aus mehreren aufeinanderfolgenden besteht. Dabei ist es durchaus so, dass z.B. Felder des zweiten Formulars von Feldern des ersten abhängig sind. Ich frage mich nun, wie ich die Formulardaten am sinnvollsten nach der Übertragung des ersten Formulars ablege, so dass ich am Ende aller Formulare alle Eingaben "schön" auslesen kann.

Zwei Möglichkeiten fallen mir auf Anhieb ein:
(a) Daten in der Session ablegen
(b) Daten serialisieren und dann in einem hidden-Feld im folgenden Formular ablegen.

Ich nutze derzeit PHP und symfony, daher würden mich Erfahrungen in diesem Bereichen besonders interessieren; anderweitige Berichte lese ich aber auch gerne.

Bis die Tage,
Matti

  1. hi,

    Zwei Möglichkeiten fallen mir auf Anhieb ein:
    (a) Daten in der Session ablegen
    (b) Daten serialisieren und dann in einem hidden-Feld im folgenden Formular ablegen.

    c) serialisiert in der Session serverseitig hintelegen ;)

    Und speichere serverseitig, das ist sicherer, damit ein Benutzer auch mal ein..zwei Schritte zurückgehen kann (also hier nicht auf den Browser verlassen). Speicherer _jeden Schritt, also die Daten jedes einzelnen Formulars und gibt diesen Objekten jeweils einen Tag: die Schrittnummer. So kann der Besucher auch mal zurück gehen und seine bisherigen Eingaben wieder sehen. Gib dem Besucher eine Navigationsleiste, damit er sehen kann, in welchem Schritt er sich befindet und zurückliegende Schritte klicken kann.

    Gib den Workflow in einer kleinen Konfigurationsdatei vor, z.B. eine ini-Datei. Hier sind auch Verzweigungen möglich (Attribute next, prev, decision).

    Viel Spaß dabei,
      Horst

    1. Tach!

      Zwei Möglichkeiten fallen mir auf Anhieb ein:
      (a) Daten in der Session ablegen
      (b) Daten serialisieren und dann in einem hidden-Feld im folgenden Formular ablegen.
      c) serialisiert in der Session serverseitig hintelegen ;)

      Die richtige Antwort lautet a. Nur wenn man keinen Session-Mechanismus zur Verfügung hat, wäre b akzeptabel. c kann nicht ernst gemeint sein (steht ja auch ein Smiley dahinter) weil das für PHP grober Unfug ohne Nutzen wäre. PHP stellt das Array $_SESSION zur Verfügung, in das man die Werte wie in andere Variablen und Arrays auch schreiben kann und sollte. Nach einer Wiederaufnahme der Session kann man ebenso einfach wieder lesend auf sie zugreifen. Ein Serialisieren bringt selbst bei komplexen Gebilden keinen Vorteil, wei dieses komplexe Gebilde auch dann nicht verlorengeht, wenn man es im Rohzustand einem $_SESSION-Element zuweist. Dass die Werte in $_SESSION unverändert bleiben, dafür sorgt PHP von sich aus. Da muss man nicht noch selbst irgendetwas absichern/verpacken wollen.

      dedlfix.

      1. Hi,

        Zwei Möglichkeiten fallen mir auf Anhieb ein:
        (a) Daten in der Session ablegen
        (b) Daten serialisieren und dann in einem hidden-Feld im folgenden Formular ablegen.
        Die richtige Antwort lautet a. Nur wenn man keinen Session-Mechanismus zur Verfügung hat, wäre b akzeptabel.

        Aber damit verhindere ich doch, dass der Workflow in zwei Browsertabs (also mit derselben Session) "gleichzeitig" bearbeitet wird. Ist das sinnvoll? Oder speicherst du die Daten in der Session unterhalb eines "Workflow"-Keys, den du zu Beginn des Workflows erzeugst?

        Bis die Tage,
        Matti

        1. Tach!

          (a) Daten in der Session ablegen
          (b) Daten serialisieren und dann in einem hidden-Feld im folgenden Formular ablegen.
          Die richtige Antwort lautet a. Nur wenn man keinen Session-Mechanismus zur Verfügung hat, wäre b akzeptabel.

          Aber damit verhindere ich doch, dass der Workflow in zwei Browsertabs (also mit derselben Session) "gleichzeitig" bearbeitet wird.

          Richtig. Von zwei Workflows in derselben Browser-Instanz war aber in deinen Anforderungen bisher nicht die Rede.

          Ist das sinnvoll? Oder speicherst du die Daten in der Session unterhalb eines "Workflow"-Keys, den du zu Beginn des Workflows erzeugst?

          Was sinnvoll ist, hängt letztlich stark von der Aufgabenstellung ab. Wenn du die Daten der jeweils nicht aktiven Formulare über den Client schleifst, sind sie ja zu einem bestimmten Zeitpunkt entweder in der Scriptinstanz auf dem Server oder in der Formularinstanz im Browser. Damit kommen sie nicht mit den Daten der anderen Workflows in Berührung, die ja in eigenen Seiten- und Script-Instanzen laufen. Sie ständig zwischen Client und Server hin- und her zu übertragen kostet aber mindestens Traffic. Die Manipulationsmöglichkeiten auf dem Client sind solange vernachlässigbar, solange es sich nur um die vom Anwender sowieso über die Formulare änderbaren Eingabedaten handelt. Bei bereits berechneten Zwischenergebnissen sieht die Sachlage jedoch schon wieder anders aus.

          Das Problem bei mehreren Workflows in demselben Browser ist im Prinzip nur vom Session-ID-Cookie verursacht, der im Browser per Domain verwaltet wird und damit in allen Tab/Fenster-Instanzen derselbe ist. Wenn die Session-ID per URL- oder POST-Parameter übertragen wird, wären damit auch getrennte Sessions auf dem Server möglich. Zumindest die URL-Variante zieht weitere Sicherheitsbedenken nach sich, die man gern vermeiden würde.

          Im Rennen ist damit noch eine für jeden Workflow eindeutige, über ein Hidden-Input separat mitgeführte Session-ID, die nur in POST-Daten, nicht jeoch über URL/GET transportiert wird. Nach dem gleichen Prinzip funktioniert der von dir vorgeschlagene Workflow-Key. Bei einer über Cookies weitergereichten Session-ID braucht es ein zweites Identifizierungsmerkmal, das einen anderen Weg gehen muss, um nicht der Cookie-Beschränkung zu unterliegen. Das kann der Workflow-Key oder besser vielleicht Workflow-ID benannt) sein. Diese W-ID kann eigentlich sogar über GET/URL übertragen werden, denn allein ohne die Session-ID im Cookie nützt sie keinem etwas.

          Getrennte Session-IDs per Cookie gehen aber auch, wenn du den Cookies individuelle Pfade mitgibst (Default ist ja /). Wenn du also deine Workflow-ID in den Pfad einbauen kannst, kannst du darüber getrennte Sessions verwalten. Das braucht dann aber weitere Maßnahmen auf dem Server, wie zu Beispiel mod_rewrite. Individuelle Subdomains gingen auch, sind aber gleich noch viel unhandlicher, weil da auch noch das DNS in Mitleidenschaft gezogen werden muss.

          Alles in allem stellt sich für mich eine ohne Verrenkungen per Cookie mitgegebene Session-ID und eine Hidden-Input-Workflow-ID als die einfachste Lösung dar.

          dedlfix.

          1. Hi,

            Aber damit verhindere ich doch, dass der Workflow in zwei Browsertabs (also mit derselben Session) "gleichzeitig" bearbeitet wird.

            Richtig. Von zwei Workflows in derselben Browser-Instanz war aber in deinen Anforderungen bisher nicht die Rede.

            Ehrlich gesagt habe ich noch nicht wirklich genau den Überblick, um meine Anforderungen zu formulieren. Ich habe zunächst einmal das Problem erkannt und versucht, Lösungen (und deren Probleme) zu finden.

            Ich hätte es ja auch Vorteil auslegen können: wenn ich den Zustand des Workflows in den Session-Daten speichere, kann ich dem Nutzer erlauben, mit dem Workflow später wieder weiterzumachen, obwohl er aus dem Workflow rausgesprungen ist... zumindest solange die Session noch da ist und er den Workflow nicht neu beginnt.

            Bei der "einfachen" Session-Lösung fände ich es (aus meiner eigenen Nutzersicht) ein wenig komisch, wenn die Applikation nur mit einem Tab funktioniert, daher meine Nachfrage.

            [... fachlich hilfreiche Informationen ...]

            Ich danke dir.

            Bis die Tage,
            Matti

            1. Bei der "einfachen" Session-Lösung fände ich es (aus meiner eigenen Nutzersicht) ein wenig komisch, wenn die Applikation nur mit einem Tab funktioniert, daher meine Nachfrage.

              Also ich definiere jetzt nochmal neu, um Missverständnisse zu vermeiden. Wenn man die Daten in SESSION-Variablen zwischenspeichert dann IST ES MÖGLICH, dass der User mehrere  Tabs verwendet, um Dein Formular auszufüllen, da in jedem Tab zunächst mal dieselbe Session-ID verwendet wird.

              Nun mal die Frage an alle: Will man denn das? ICh könnte mir vorstellen, dass man das nicht möchte, da Du ja auch sagst, die Seiten 2,3,... etc können abhängig sein von 1. Bspw.
              Ich könnte mir vorstellen, dass da ein ziemlicher Salat rauskommt. Bei heiklen Sachen mache ich es immer so, dass ich eine CID (Click-ID) per URL durchs Formular reiche, die bei Seitenaufbau generiert parallel in einer Sessionvariable mitgespeichert wird. So ungefähr:

              define('TS',   time());  
              define('mTS',  TS.substr(microtime(),2,6));  
                
              if(isset($_POST["CID"]){  
                if($_POST["CID"] != $_SESSION["CID"]){  
                  //jetzt raste aus  
                }  
              }  
                
              $_SESSION["CID"] = mTS;  
                
              $Form  = "<form>";  
              $Form .= "<input type='hidden' name='CID' value='".mTS."' >";  
              $Form .= "</form>";
              

              Wenn die ungleich sind, verliert das ganze gleich mal seine Gültigkeit. Ist das unfreundlich?
              Wie ist es denn am besten?

              Cheers,
              Baba

              1. Tach!

                Bei der "einfachen" Session-Lösung fände ich es (aus meiner eigenen Nutzersicht) ein wenig komisch, wenn die Applikation nur mit einem Tab funktioniert, daher meine Nachfrage.

                Also ich definiere jetzt nochmal neu, um Missverständnisse zu vermeiden. Wenn man die Daten in SESSION-Variablen zwischenspeichert dann IST ES MÖGLICH, dass der User mehrere  Tabs verwendet, um Dein Formular auszufüllen, da in jedem Tab zunächst mal dieselbe Session-ID verwendet wird.

                Hast du vielleicht ein NICHT vergessen? Dann würde deine Aussage meiner Meinung nach stimmen und auch zum Rest deiner Ausführungen passen.

                [code lang=php]define('TS',   time());
                define('mTS',  TS.substr(microtime(),2,6));

                microtime() hat doch nun schon soooo lange einen boolschen Parameter bekommen, der bei true die Zeit als Float und nicht diesen zerhackten String zurückgibt. Warum verwendet den denn keiner?

                if(isset($_POST["CID"]){
                  if($_POST["CID"] != $_SESSION["CID"]){
                    //jetzt raste aus
                  }
                }

                Die CID kannst du aber in der Form nur für die Überprüfung der Workflowreihenfolge verwenden, also dass wirklich Schritt für Schritt durchgelaufen wird. Für das Separieren mehrerer paralleler Workflows ist solch ein Singleton-Wert nicht geeignet. Dafür brauchts die Workflow-ID als Key mit den restlichen Daten als Array oder Baumstruktur dahinter.

                Wenn die ungleich sind, verliert das ganze gleich mal seine Gültigkeit. Ist das unfreundlich?
                Wie ist es denn am besten?

                Kommt auf die Aufgabenstellung an. Wenn wirklich die Tippeltappeltour stattfinden muss, dann kann man das so durchziehen. Wenn lediglich ein Parameter aus Formular 1 für Formular 2 wichtig ist, reicht es doch zunächst, nur diesen als Pflicht zu überprüfen, solange man sich vorwärts und rückwärts durch die Schritte bewegen kann, um die anderen Pflichtparameter (aus der Sicht des Gesamtergebnisses) später auszufüllen.

                Aber wir weichen vom Thema ab. Es ging darum, mehrere Workflows zu parallelisieren und nicht die serielle Abarbeitung von einem sicherzustellen.

                dedlfix.

            2. Tach!

              Bei der "einfachen" Session-Lösung fände ich es (aus meiner eigenen Nutzersicht) ein wenig komisch, wenn die Applikation nur mit einem Tab funktioniert, daher meine Nachfrage.

              Ich kenne das nicht anders bei Bestellungen. Mir ist noch kein Shop aufgefallen, der unbeeinflusste Bestell-Workflows in derselben Browser-Instanz zulässt. Ich suche aber auch mengels Bedarf nicht gezielt danach.

              dedlfix.

      2. Moin,

        Zwei Möglichkeiten fallen mir auf Anhieb ein:
        (a) Daten in der Session ablegen
        (b) Daten serialisieren und dann in einem hidden-Feld im folgenden Formular ablegen.
        c) serialisiert in der Session serverseitig hintelegen ;)

        Die richtige Antwort lautet a. Nur wenn man keinen Session-Mechanismus zur Verfügung hat, wäre b akzeptabel. c kann nicht ernst gemeint sein (steht ja auch ein Smiley dahinter) weil das für PHP grober Unfug ohne Nutzen wäre. PHP stellt das Array $_SESSION zur Verfügung, in das man die Werte wie in andere Variablen und Arrays auch schreiben kann und sollte. Nach einer Wiederaufnahme der Session kann man ebenso einfach wieder lesend auf sie zugreifen. Ein Serialisieren bringt selbst bei komplexen Gebilden keinen Vorteil, wei dieses komplexe Gebilde auch dann nicht verlorengeht, wenn man es im Rohzustand einem $_SESSION-Element zuweist. Dass die Werte in $_SESSION unverändert bleiben, dafür sorgt PHP von sich aus. Da muss man nicht noch selbst irgendetwas absichern/verpacken wollen.

        Unsinnige Diskussion. Das Wichstigste ist, den Workflow als Template vorzugeben und die einzelnen Schritte zu taggen. Design Pattern: State Transition.

        Mfg, Rolf

        1. Hi,

          Unsinnige Diskussion. Das Wichstigste ist, den Workflow als Template vorzugeben und die einzelnen Schritte zu taggen. Design Pattern: State Transition.

          Bitte erkläre, was du damit sagen willst.

          Bis die Tage,
          Matti