Rouven: Web-Assistent

Hallo,

ich hab mal eine Frage, bei deren Beantwortung vielleicht etwas Erfahrung im Bereich Web-Anwendungen hilfreich ist.
Ich möchte einen Benutzer einen etwas umfangreicheren Vorgang durchführen lassen (hier geht es z.B. um die Erstellung eines Benutzer-Kontos, bei dem viele Einstellungen vorgenommen werden müssen). Was mir dabei nicht gefallen würde, wäre eine riesig lange Webseite mit einem Formular, die den Benutzer erschlägt.
Die Lösung für mich lag nah, das ganze als Assistent mit mehreren Schritten aufzubauen - Technisch ist das ganze für eine PHP+MySQL-Umgebung vorgesehen.
Nun gibt es dafür ja mal mindestens zwei Möglichkeiten, eine etwas direktere (was mehr Assistenten-Feeling aufkommen lassen würde (subjektive Meinung)) mit mehreren DIVs, die sich halt nacheinander einblenden (was aber vermute ich mal JavaScript erfordern würde, was aber auf der Seite z.T. sowieso erforderlich ist) oder eben mehrere Formulare mit einer Vor/Zurück-Möglichkeit und einer Zwischenspeicherung in Session oder Hidden-Feldern.
Meine Frage(n) nun hierzu:

  • Gibt es noch weitere innovative Vorschläge?
  • Was ist die technisch "beste" (nach Erfahrungen) Lösung?

Danke für alle Tipps!

MfG
Rouven

--

-------------------
ss:) zu:) ls:& fo:) de:< va:{ ch:? sh:) n4:( rl:? br:$ js:| ie:) fl:(
  1. Hallo Rouven,

    • Gibt es noch weitere innovative Vorschläge?

    Ich wüßte nichts...

    • Was ist die technisch "beste" (nach Erfahrungen) Lösung?

    IMHO mit Sessions.

    a) funktioniert das auch mit ohne JS
    b) brauchst Du im Gegensatz zu Hidden-Feldern die Validierung nur einmal pro Formular durchführen

    Das einzige Problem bei der ganzen Geschichte ist Vor/Zurück. Denn bei POST-Formularen ist es ätzend, mit Zurück zu navigieren.

    Ich würde daher das ganze so lösen:

    1. Ein Script, das das Formular anzeigt. Nennen wir es mal form.php. Dieses Script erhält einen Parameter, nämlich die Seitennummer. Bei einer ungültigen oder keiner Seitennummer wird automatisch die Seite 1 angezeigt. Falls die Seitennummer gültig ist, jedoch in einer vorigen Seite noch keine erfolgreichen Eingaben gemacht wurden, wird diejenige Seite, auf der noch keine Eingaben gemacht wurden, angezeigt. Ansonsten wird die Seite, die angefragt wurde, angezeigt.

    2. Ein Script, das das Formular verarbeitet. Nennen wir es mal post.php. Dieses Script verarbeitet die Eingaben und leitet _dann_ auf form.php mit der nächsten Seite weiter. Dadurch wird die Vor/Zurück-Funktionalität erhalten. Dazu unten etwas mehr.

    Die Daten könntest Du in einer Session-Variable $_SESSION['pages'] abspeichern. Diese sollte als Schlüssel die Seitennummer haben. Als Werte sollte ein assoziatives Array sein, dass drei Elemente enthält: 'filled_in', 'form_data', 'validated_data' und 'form_errors'. filled_in ist entweder true oder false, das gibt an, ob das Formular ausgefüllt wurde *und* die Validierung erfolgreich war. form_data enthält die rohen Formulardaten, falls die Validierung fehlgeschlagen ist. validated_data enthält die validierten Daten. form_errors enthält alle Fehlermeldungen, die bei der Validierung aufgetreten sind.

    Über $_SESSION['pages'][0]['filled_in'] kannst Du feststellen, ob die Seite 1 ausgefüllt wurde.

    Wenn nun form.php etwas anzeigen soll und bereits die richtige Seitennummer (s.o.) kennt, dann soll sie über $_SESSION['pages'][$nummer]['filled_in'], ob das Formular korrekt ausgefüllt wurde. Falls ja, soll sie die Daten aus $_SESSION['pages'][$nummer]['validated_data'] nehmen und nochmal das Formular anzeigen. Falls nein, soll sie die Daten aus $_SESSION['pages'][$nummer]['form_data'] nehmen und nochmal das Formular anzeigen. Dabei soll sie alle Fehlermeldungen in $_SESSION['pages'][$nummer]['form_errors'] anzeigen.

    Wenn nun ein POST-Request auf post.php ankommt, dann muss post.php erst einmal prüfen, ob dieser Request überhaupt gültig war, d.h. diese Seite bereits ausgefüllt werden durfte. Wenn das der Fall ist, muss post.php die Eingabe validieren. Falls die Eingabe valide ist, soll $_SESSION['pages'][$nummer]['validated_data'] gefüllt werden, $_SESSION['pages'][$nummer]['filled_in'] auf true gesetzt werden und auf form.php mit einer Seitennummer größer weitergeleitet werden. Falls die Daten nicht valide sind, soll $_SESSION['pages'][$nummer]['filled_in'] auf false gesetzt werden, $_SESSION['pages'][$nummer]['form_data'] und $_SESSION['pages'][$nummer]['form_errors'] gefüllt werden und $_SESSION['pages'][$nummer]['validated_data'] gelöscht werden. Nun soll auf form.php mit der aktuellen Seitennummer weitergeleitet werden.

    Die Weiterleitung solltest Du, falls der Browser die Anfrage über HTTP/1.1 schickt, über einen Status 303 (der für Weiterleitungen nach POST vorgesehen ist, allerdings erst in HTTP/1.1) machen:

    if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') {
      Header ('HTTP/1.1 303 See Other');
    }

    Ansonsten lässt Du PHP automatisch den 302er schicken. Daraufhin sendest Du den normalen Location-Header.

    So würde ich das lösen... ich hoffe Du verstehst, was ich meine. :)

    Viele Grüße,
    Christian

    1. Hi Christian,

      erst einmal danke für die lange Antwort, ich habe mir noch nicht allzu viele Gedanken gemacht, aber die Sache mit dem Array in der Session ist auf jeden Fall mal eine sehr gute Idee - hätt' ich auch selber drauf kommen können...
      Das einzige, was mir an diesem Multiple-Webseiten-Formular-Lösung-Dings auf die Nerven geht ist die Wartezeit. Ich fände natürlich eine DIV-Lösung besser (wie ich schon im Originalposting meinte) - der User hat immer schneller das Formular vor Augen, wenn ich bei einem Modem immer wieder auf die neue Seite warten muss, geht mir das auf den Keks (zumal man ja den Unterschied zwischen "ich muss warten, weil der Server was prüft" und "ich warte weil die Seite so lang ist" nicht so direkt merkt). Aber dennoch, ist natürlich ohne JS die Lösung erst einmal vorzuziehen.

      if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') {
        Header ('HTTP/1.1 303 See Other');
      }

      Nur die Sache mit der Weiterleitung nicht so ganz klar war, warum in 3 Teufels Namen sollte ich einen Unterschied zwischen HTTP 1.1 und dem Rest machen (ich kenn mich da nicht so aus, ich dachte der Standard-Location-Header würde es schon tun, oder ist das ein Problem mit dem POST-Formular?)

      MfG
      Rouven

      --

      -------------------
      ss:) zu:) ls:& fo:) de:< va:{ ch:? sh:) n4:( rl:? br:$ js:| ie:) fl:(
      1. Hallo Rouven,

        (ich kenn mich da nicht so aus, ich dachte der Standard-Location-Header würde es schon tun, oder ist das ein Problem mit dem POST-Formular?)

        Jain, es ist kein wirkliches Problem in heutigen Browsern. Das eigentliche Problem ist die Tatsache, dass 302 nicht explizit sagt, dass die Methode, mit der auf die darauffolgende Resource zugegriffen werden muss, GET sein muss. Ich habe zwar noch keinen Browser erlebt, der es anders macht, allerdings ist das Verhalten an dieser Stelle einfach nicht definiert.

        In HTTP/1.1 wurden die Statuscodes 303 und 307 eingeführt, um diese Unklarheit zu beseitigen. 303 sagt: der nächste Request muss GET sein. 307 sagt: derr nächste Request muss POST sein.

        Daher: Für HTTP/1.1-Clients einen 303er senden, dann ist man auf der sicheren Seite, für HTTP/1.0-Clients einen 302er senden, da diese 303 noch nicht kennen (können). Der 302er wird von PHP bei Location automatisch generiert, falls noch kein 30x-Header gesendet wurde.

        Viele Grüße,
        Christian

  2. Moin!

    Ich möchte einen Benutzer einen etwas umfangreicheren Vorgang durchführen lassen (hier geht es z.B. um die Erstellung eines Benutzer-Kontos, bei dem viele Einstellungen vorgenommen werden müssen). Was mir dabei nicht gefallen würde, wäre eine riesig lange Webseite mit einem Formular, die den Benutzer erschlägt.

    Welche Vorkenntnisse kannst du vom Benutzer erwarten? Macht der das häufiger?

    Meine Frage(n) nun hierzu:

    • Gibt es noch weitere innovative Vorschläge?
    • Was ist die technisch "beste" (nach Erfahrungen) Lösung?

    Bei Licht betrachtet ändert es nichts an der Menge abzufragender Informationen, egal wie du die Formularfelder präsentierst. Es ist deshalb die Frage, wie du die Menge an Informationen präsentierst.

    Ich würde deshalb die ewig lange Formularseite nicht grundsätzlich ausschließen. Es geht im Prinzip nur darum, das Formular benutzerfreundlich, also übersichtlich zu gestalten.

    Es hängt deshalb stark davon ab, wozu das Formular benutzt wird. Kann man das von oben nach unten nacheinander sinnvoll ausfüllen? Eventuell mit hilfreichen Texten zwischendrin? Was spricht dann dagegen, das Formular in einem Stück bearbeiten zu lassen?

    Ein schlechtes Beispiel für ein "am-Stück-Formular" ist übrigens die Benutzereinstellung in diesem Forum.
    http://forum.de.selfhtml.org/cgi-bin/user/fo_userconf
    Da findet man leider auf Anhieb absolut nichts. Die Informationen sind auch nicht sinnvoll gruppiert und zusammengefaßt. Das ist alles der internen Programmstruktur anzulasten, die derzeit einfach keine bessere Darstellung zuläßt - das Formular generiert sich aus den anderswo konfigurierten Einstellmöglichkeiten, für Gruppierungen und schön formatierte erklärende Texte ist da nichts vorgesehen.

    - Sven Rautenberg

    --
    ss:) zu:) ls:[ fo:} de:] va:) ch:] sh:) n4:# rl:| br:< js:| ie:( fl:( mo:|