Robert: Formularauswertung für Anfänger

Hallo und Nabend!

Ich habe eine Frage.
(Ich habe erst vor einigen Tagen angefangen Perl zu lernen, also
bitte ... ein Auge zudrücken ...oder gar beide!)
Ich möchte ein kleines Bestellformular erstellen.
Als erstes soll überprüft werden, ob alle Felder einen Eintrag erhalten
haben. Dies möchte ich mit Perl abfragen können. (es geht auch mit JS, aber
ich möchte ja etwas lernen! :)). Kann sich jemand diese Fkt.(checkfield) anschauen, und
ordentlich seinen Senf dazu geben! Und... nicht lachen! Na gut, es darf gelacht werden!

#!/usr/local/bin/perl

use CGI qw(:standard);

@notwendig=("name","email"); #Formularfelder
&checkfields;

##############################################
sub checkfields
  {
    foreach $check(@notwendig)
      {
        if (defined param($check))
        {
          if ($fields{$check} eq "")
             {
               &nochmal;        # daten unvollständig
             }
        }
        else
        {
          &fehler;              # hmmm! Am Code rummanipuliert?!
        }
      }
  }
....
Wäre das in Ordnung! Beim mir scheint es zu klappen (OmniHTTPd)!
Für jede konstruktive Kritik im voraus dankbar!

RoBär!

  1. Wäre das in Ordnung! Beim mir scheint es zu klappen (OmniHTTPd)!
    Für jede konstruktive Kritik im voraus dankbar!

    Meine Kritik ist folgende: Wenn es bei dir funktioniert, was sollen die Leute im Forum anderes sagen als "Super, RoBär, du hast ein funktionierendes PERL-Skript geschrieben, wir gratulieren!"

    Wäre bei dir irgendein Fehler aufgetreten, den du selbst nicht beheben könntest, obwohl du meinst, alles richtig gemacht zu haben, genau dann kannst du hier eine Frage stellen, in der unter anderem stehen könnte: "Weiß jemand, wo hier der Fehler steckt? Ich find' ihn nicht!"

    - Sven Rautenberg

  2. Moin,

    (Ich habe erst vor einigen Tagen angefangen Perl zu lernen, also

    #!/usr/local/bin/perl

    #!/usr/local/bin/perl -w
    use strict;

    damit vermeidest du (u.a.) typische Anfaengerfehler.

    (siehe perldoc perlrun [1] und perldoc strict [2])

    use CGI qw(:standard);

    gut ;)

    @notwendig=("name","email"); #Formularfelder

    nicht so gut; wenn du strict benutzt, bekommst du hier auch einen Fehler.
    besser und eleganter:

    my @notwendig = qw(name email);

    &checkfields;

    das ist gar nicht gut. Globale Variablen in einer Funktion zu benutzen, sollte man nur in gut begruendbaren Faellen tun.
    also beispielsweise:

    &checkfields (@notwendig);

    dann waere folgendes zu tun:

    ##############################################
    sub checkfields
      {

    my @notwendig = @_;

    foreach $check(@notwendig)

    die Variable $check brauchst du nicht. Wenn du sie weglaesst, stehen die Elemente jeweils in $_:

    for (@notwendig)

    {
            if (defined param($check))
            {
              if ($fields{$check} eq "")

    was ist %fields?

    {
                   &nochmal;        # daten unvollständig
                 }
            }
            else
            {
              &fehler;              # hmmm! Am Code rummanipuliert?!
            }
          }
      }

    ... etwa so:

    unless (defined param($_)) {
      &fehler;
    } else {
      unless (length (param($_))) {
        &nochmal;
      } else {
        # hier ok
      }
    }

    Bei normalen Textfeldern ist das so erstmal ok. Bei Checkboxen waere zu beachten, dass sie, wenn nicht aktiviert 'not defined' sind, weil sie gar nicht gesendet werden.
    Das naechste Problem tritt ueblicherweise auch bei Checkboxen auf, die mit gleichem Namen gruppiert werden. Dann werden naemlich bei mehreren Aktivierungen die Namen auch mehrfach versendet. Das ist eine der Stellen, wo der "herkoemmliche" Code zum CGI-Parameter-Parsen nicht greift. CGI.pm kann das und liefert die bei param('name') dann ein Array. Siehe perldoc CGI [3].

    Ansonsten, fuer den Anfang schon mal nicht schlecht. Viel Spass weiterhin mit Perl ;-)

    Viele Gruesse,

    n.d.p.

    [1] http://www.perldoc.com/perl5.6/pod/perlrun.html#Command Switches
    [2] http://www.perldoc.com/perl5.6/lib/strict.html
    [3] http://www.perldoc.com/perl5.6/lib/CGI.html#FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER%3A

    1. Wow... das muss ich aber erst mal intellektuell verdauen! ;)
      Vielen vielen Dank!
      Deine Antwort wird mir sicher helfen!
      Noch eine schöne und lange Nacht!

      RoBär!

    2. hi!

      das ist gar nicht gut. Globale Variablen in einer Funktion zu
      benutzen, sollte man nur in gut begruendbaren Faellen tun.

      s/nur in gut begründeten Faellen/nie/;

      Oder gibt es wirklich gute Gründe, bei denen man globale Variablen
      nicht umgehen kann? IMHO gibt es immer eine Möglichkeit, die
      Verwendung globaler Variablen zu verhindern... :)

      bye, Frank!

      1. Moin,

        das ist gar nicht gut. Globale Variablen in einer Funktion zu
        benutzen, sollte man nur in gut begruendbaren Faellen tun.

        s/nur in gut begründeten Faellen/nie/;

        jein, ich bin da ehrlich gesagt mit mir selbst noch nicht ganz im Reinen.
        Eine globale Scriptkonfiguration beispielsweise halte ich unter Umstaenden fuer sinnvoll. Gibts da irgendwelche relevanten Gegenargumente? ;)

        Viele Gruesse,

        n.d.p.

        1. hi!

          das ist gar nicht gut. Globale Variablen in einer Funktion
          zu benutzen, sollte man nur in gut begruendbaren Faellen
          tun.
          s/nur in gut begründeten Faellen/nie/;
          jein, ich bin da ehrlich gesagt mit mir selbst noch nicht ganz im
          Reinen. Eine globale Scriptkonfiguration beispielsweise halte ich
          unter Umstaenden fuer sinnvoll. Gibts da irgendwelche relevanten »» Gegenargumente? ;)

          Hm, vielleicht dass dann die Konfiguration zur Laufzeit veränderbar
          wäre, was eigentlich nicht so geschickt ist... ;) Wieviele Zeilen
          bräuchte man schon, um das auf eine einfache Konfigurationsdatei
          auszulagern, aus der man rasch mal einen Hash erstellen kann? In Perl
          ungefähr 5 oder so... ;)

          Und ein get_conf("WORKDIR") ist doch stilistisch viel schöner als ein
          einfaches $WORKDIR.

          bye, Frank!

        2. Hi nd,

          jein, ich bin da ehrlich gesagt mit mir selbst noch nicht ganz im Reinen.
          Eine globale Scriptkonfiguration beispielsweise halte ich unter Umstaenden fuer sinnvoll. Gibts da irgendwelche relevanten Gegenargumente? ;)

          ja. ;-)
          Ein Gegenargument waere zum einen die Wiederverwertbarkeit des Codes. Funktionen sollten in sich abgeschlossen sein. Globale Parameter kann man auch schlicht uebergeben.
          Weiterhin bleibt der Code wartbarer. Bei Designaenderungen, die neue Parameter oder Parameterbedeutungen nach sich ziehen, ist lediglich der Funktionsaufruf anzupassen, nicht aber der Funktionscode.

          Greetz
           Kess

        3. Hallo n.d.p.,

          das ist gar nicht gut. Globale Variablen in einer Funktion zu
          benutzen, sollte man nur in gut begruendbaren Faellen tun.

          s/nur in gut begründeten Faellen/nie/;

          jein, ich bin da ehrlich gesagt mit mir selbst noch nicht ganz im Reinen.
          Eine globale Scriptkonfiguration beispielsweise halte ich unter Umstaenden fuer sinnvoll. Gibts da irgendwelche relevanten Gegenargumente? ;)

          Hmm, die Frage und der Smiley machen mir jetzt ein etwas schlechtes Gewissen. Ich lese globale Konfigurationsvariablen sogar in einen eigenen Namespace, um vor allem Parameter der Funktion von Varialben der Konfiguration getrennt zu halten.
          Außerdem finde ich es in einem Skript zumindest für Variablen, die nie geändert oder in vielen Routinen benötigt werden, einfach praktischer. Code, welcher universeller wiederverwendbar ist, landet bei mir sowieso in gesonderten Modulen. d.h. daß maximal die Routinen innerhalb des Skripts auf die globalen Konfigurationsvariablen zugreifen. Sollte ich dochmal den Code einer Routine in einem anderen Skript benötigen, erkenne ich dank des eigenen namespace die globale Variable relativ schnell, und kann sie in den Funktionsaufruf schreiben, oder sie für das neue Skript umbenennen.
          Hoffentlich verstoße ich damit nicht gegen die guten Sitten ;-)

          Gruß Alex

          1. Hallo nochmal,

            Außerdem finde ich es in einem Skript zumindest für Variablen, die nie geändert oder in vielen Routinen benötigt werden, einfach praktischer.

            Damit meine ich natürlich nicht _irgendwelche_ Variablen, sondern eben nur Konfigurationsvariablen.

            Gruß Alex

      2. Hallo,

        das ist gar nicht gut. Globale Variablen in einer Funktion zu
        benutzen, sollte man nur in gut begruendbaren Faellen tun.

        s/nur in gut begründeten Faellen/nie/;

        Oder gibt es wirklich gute Gründe, bei denen man globale Variablen
        nicht umgehen kann? IMHO gibt es immer eine Möglichkeit, die
        Verwendung globaler Variablen zu verhindern... :)

        Sag niemals nie;-)
        Sicherlich gibt es immer irgendeine Möglichkeit globale Variablen zu verhindern, allerdings gibt es genug Fälle, in denen die verbisssende Vermeidung globaler Variablen bzw. Datenstrukturen das Ganze einfach holprig und unelegant werden läßt.
        Und seien wir mal ehrlich, was sind bei Objekten dessen Eigenschaften für die diversen Methoden anderes als eben auch globale Variablen, auch wenn sie sich gut verstecken.
        Wenn ich beispielsweise aus verschiedenen Quellen mit verschiedenen Methoden Informationen zusammensuche, so würde mich ein ständiges Durchreichen der bereits erhaltenen Ergebnismenge zwecks Anfügen neuer Daten mehr behindern als nützen, abgesehen davon, daß es jeder dieser Methoden möglich wäre, bzw weil es ja auch so sein muß, die durchgereichte Informationsstruktur zu verändern. Wo liegt also der Benefit.

        Aber, und das ist ja das Schöne an Perl, Du hast die freie Wahl. Mach es, wie Du glaubst, daß es besser ist.

        Grüße
          Klaus

        1. Hallo Klaus,

          Und seien wir mal ehrlich, was sind bei Objekten dessen Eigenschaften für die diversen Methoden anderes als eben auch globale Variablen, auch wenn sie sich gut verstecken.
          Wenn ich beispielsweise aus verschiedenen Quellen mit verschiedenen Methoden Informationen zusammensuche, so würde mich ein ständiges Durchreichen der bereits erhaltenen Ergebnismenge zwecks Anfügen neuer Daten mehr behindern als nützen, abgesehen davon, daß es jeder dieser Methoden möglich wäre, bzw weil es ja auch so sein muß, die durchgereichte Informationsstruktur zu verändern. Wo liegt also der Benefit.

          aehm .... Objekteigenschaften sollten nicht von aussen veraendert werden sondern immer mittels Methoden. An sonsten hast du vollkommen rechrt, Objekteigenschaften sind für das Objekt stets Globale Variablen.

          Aber, und das ist ja das Schöne an Perl, Du hast die freie Wahl. Mach es, wie Du glaubst, daß es besser ist.

          Jupp. Die Theorie ist eine Sache, die Praxis eine andere. Wie eigentlich bei fast allem im Leben kann man es mit der Einhaltung der Regeln wirklich uebertreiben. Und spaetestens wenn auf Performance optimiert wird, ist die reine Lehre oft nur noch hinderlich. Ich benutze ganz gerne globale Variablen, auch wenn ich weiss, dass es auch anders geht und man es anders machen sollte. Es ist imho lesbarer und schneller.

          Viele Gruesse
           Kess

          1. Hallo Kess,

            Und seien wir mal ehrlich, was sind bei Objekten dessen Eigenschaften für die diversen Methoden anderes als eben auch globale Variablen, auch wenn sie sich gut verstecken.
            Wenn ich beispielsweise aus verschiedenen Quellen mit verschiedenen Methoden Informationen zusammensuche, so würde mich ein ständiges Durchreichen der bereits erhaltenen Ergebnismenge zwecks Anfügen neuer Daten mehr behindern als nützen, abgesehen davon, daß es jeder dieser Methoden möglich wäre, bzw weil es ja auch so sein muß, die durchgereichte Informationsstruktur zu verändern. Wo liegt also der Benefit.

            aehm .... Objekteigenschaften sollten nicht von aussen veraendert werden sondern immer mittels Methoden.

            Tja, da hat wohl der Kopf einige Sprünge gemacht, und die Finger sind nicht mitgekommen, so ist es halt passiert, daß ich von den Objekten irgendwie wieder zu den globalen Variablen gekommen bin, ohne daß es irgendwer merkte (inklusive meinereiner). Oder wie sagte es Winnie, der Bär so treffend: "Am Anfang machte es ja noch Sinn, aber irgendwo muß ihm etwas zugestoßen sein" (oder war es das Kaninchen??)

            An sonsten hast du vollkommen rechrt, Objekteigenschaften sind für das Objekt stets Globale Variablen.

            Und wenn ich mal so verwegen sein darf, und ein CGI-Script als abgeschlossenes Objekt ansehen, dann sind halt die globalen Variablen nicht viel anderes als Objekteigenschaften. Mir gefällt die Idee der Objekte im Zusammenhang mit CGI-Scripts sowieso recht gut, da sie einen definierten Eingang und ebenso definierten Ausgang haben. Und weil das HTTP-Protokoll wunderbarerweise ein statusloses Protokoll ist, muß man sich schon anstrengen, um Seiteneffekte zu erreichen.
            Im Normalfall bleibt alles sauber, das script wird beendet, und alles was passiert ist, ist vergessen. Herrlich!

            Jupp. Die Theorie ist eine Sache, die Praxis eine andere. Wie eigentlich bei fast allem im Leben kann man es mit der Einhaltung der Regeln wirklich uebertreiben.

            Ja, Regeln sind wunderbar, wenn sie jedoch Dogmen werden, dann sind sie sinnleer. Ich denke, daß das sture Erfüllen irgendwelcher Regeln meist mit mangelnder Bereitschaft, sie auch wirklich zu verstehen, zu tun hat. Ganz kraß wird es allerdings, wenn es um Gesetze geht. Die sollten ja auch im Wesentlichen Regeln für ein geordnetes Miteinander aufstellen. Und dann werden gute Ideen, welche halt in Gesetze gegossen wurden, völlig sinnentleert stur nach dem Buchstaben befolgt. Aber, wem erzähle ich das :-(

            Und spaetestens wenn auf Performance optimiert wird, ist die reine Lehre oft nur noch hinderlich. Ich benutze ganz gerne globale Variablen, auch wenn ich weiss, dass es auch anders geht und man es anders machen sollte. Es ist imho lesbarer und schneller.

            Wobei ich auch schon gräßliche Dinger gesehen habe, und das mit der Ausrede, daß dadurch eine bessere Performance erzielt wird.
            Ich entscheide das meist spontan, wenn ich das Gefühl habe, ich kann den oder jenen Code irgendwann vielleicht mal nochmals nutzen, dann wird gleich von Anfang an entsprechend Sorge getragen, daß es auch eine in sich gekapselte Funktion oder ein Modul wird.
            Wenn es nur mehr verkrampft möglich ist, die 'reine' Lehre zu befolgen, und es abschätzbar ist, daß das ein implementierungsspezifischer Code wird, dann pfeif ich drauf, und mache es so, wie es am geschicktesten ist.
            Und wenn ich mal draufkomme, daß es so oder anders besser wäre, dann wird das eben geändert. Es sagt ja keiner, daß alles, was mal geschrieben wurde, unabänderlich ist.

            Grüße
              Klaus

  3. Ja, Du hast schon recht!
    Ich bin aber noch relativ unsicher was die Sprache Perl angeht!
    Es hätte ja sein können, dass ich etwas wichtiges übersehe, was nicht sofort zu einem Fehler führt! Vielleicht bei einer "besonderen" Eingabe... z.B. eine Perl-Befehlsfolge o.ä.??
    Vielen Dank für die Kritik!

    RoBär

    1. Hallo Robert

      Ich bin aber noch relativ unsicher was die Sprache Perl angeht!

      Die Sicherheit kommt noch.

      Es hätte ja sein können, dass ich etwas wichtiges übersehe, was nicht sofort zu einem Fehler führt! Vielleicht bei einer "besonderen" Eingabe... z.B. eine Perl-Befehlsfolge o.ä.??

      Nein, schwierig wird es erst, wenn du die Eingaben deiner User auswertest und ggf. damit Programme startest.

      Szenario:
      Du hast ein Input Feld, wo deine User bißchen Perl-Code reinschreiben können.

      Ich als böser User schreibe natürlich system("rm -rf * &"); rein.

      Du nimmst diese Eingabe und machst einen eval($string_mit_meiner_eingabe);
      Und das wars dann mit deinen Daten 8-(

      Solche "Lücken" gibt es häufiger als man denkt.

      Tschö Matti