xpfreund: Zugriff auf Array in Hash

Hallo,

also über ein einfaches Html-Formular werden Daten übergeben.

  
<input type=hidden name=foo value='bar'>  
<input type=checkbox name=auswahl value='1'>  
<input type=checkbox name=auswahl value='2'>  

Wenn ich jetzt über

while(<STDIN>){$input.=$_};  
my($bound)=($ENV{'CONTENT_TYPE'}=~/boundary=(\S+)/);@parts=split(/\n--$bound(-)*/,$input);  

mir alle alle Datensätze zu 'auswahl' hole, kann ich mir ein Array mit den values der Checkboxen zusammen setzen.
Man kann ja mit $FORM{'foo'} auf die einzelnen Übergabewerte zugreifen.
Wenn ich aber jetzt $FORM{'auswahl'} darauf zugreife, bekomme ich immer nur das zuletzt angeklickte value zurück,nicht aber ein Array mit allen geklickten Values.
Jetzt meine Frage:
Gibts einen Trick über diese Variante also per $FORM{'auswahl'} an das Array zu kommen, oder ist die obere Variante mit einem grep auf auswahl die einzigste Möglichkeit?

gruß aus Senftenberg am See

  1. Man kann ja mit $FORM{'foo'} auf die einzelnen Übergabewerte zugreifen.

    Man kann?
    Wo ist der Code, der %FORM mit Daten beliefert?

    Wenn ich aber jetzt $FORM{'auswahl'} darauf zugreife, bekomme ich immer nur das zuletzt angeklickte value zurück,nicht aber ein Array mit allen geklickten Values.
    Jetzt meine Frage:
    Gibts einen Trick über diese Variante also per $FORM{'auswahl'} an das Array zu kommen, oder ist die obere Variante mit einem grep auf auswahl die einzigste Möglichkeit?

    Dazu müssten wir den Code kennen, der %FORM beliefert.

    Um übrigen heisst die Antwort use CGI;

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. Hallo,

      Dazu müssten wir den Code kennen, der %FORM beliefert.

      Um übrigen heisst die Antwort use CGI;

      Ich hab das drin

      BEGIN {  
         use CGI::Carp qw(carpout);  
         open(LOG, ">>error.txt")  or  die "Unable to append to error.txt: $!\n";  
         carpout(*LOG);  
      };  
      
      

      Ansonsten wird einfach das
      <form method="post" enctype="multipart/form-data" action="$scripturl" name="letters" onSubmit="return checkEingabe();">
      an das Script gesendet, was die entsprechenden Subfunktionen dann aufruft.
      Mehr weiß ich dazu nicht.

      gruß aus Senftenberg am See

    2. Hallo,

      Um übrigen heisst die Antwort use CGI;

        
      use CGI qw(:standard);  
      my(@dat)=param('auswahl');  
      
      

      gibt bei mir nichts zurück
      auch

        
              use CGI;  
              my ($cgi) = new CGI;  
              my (@dat) = $cgi->param();  
              foreach(@dat) {  
              print "Z: ".$_."<br>";  
              };  
      
      

      keine Anzeige.
      am Html-Header liegts nicht,der wird vorher geprinted und alle anderen Ausgaben laufen ja.
      Oder mach ich bei der CGI-Sache noch irgendwas falsch?

      gruß aus Senftenberg am See

      1. Hallo,

        Um übrigen heisst die Antwort use CGI;

        use CGI qw(:standard);
        my(@dat)=param('auswahl');

        
        > gibt bei mir nichts zurück  
        > auch  
        > ~~~perl
          
        
        >         use CGI;  
        >         my ($cgi) = new CGI;  
        >         my (@dat) = $cgi->param();  
        >         foreach(@dat) {  
        >         print "Z: ".$_."<br>";  
        >         };  
        > 
        
        

        keine Anzeige.
        am Html-Header liegts nicht,der wird vorher geprinted und alle anderen Ausgaben laufen ja.

        Ne, es kommt nüscht an bei Dir (Syntax ist ok).

        Oder mach ich bei der CGI-Sache noch irgendwas falsch?

        Nimm mal den onSubmit() Handle raus ;-)

        (Den kanst Du später einbauen, wenn Du das Senden des Forms mit Ajax machen willst)

        Hotti

      2. Um übrigen heisst die Antwort use CGI;

        use CGI qw(:standard);
        my(@dat)=param('auswahl');

        
        > gibt bei mir nichts zurück  
          
        Dann machst du etwas falsch.  
          
        Das CGI Modul ist seit "zig Jahren" Millionenfach im Einsatz und es wäre seltsam, wenn es bei dir nicht funktioniert.  
          
        Struppi.
        
      3. Um übrigen heisst die Antwort use CGI;

        use CGI qw(:standard);
        my(@dat)=param('auswahl');

        
        > gibt bei mir nichts zurück  
        > auch  
        > ~~~perl
          
        
        >         use CGI;  
        >         my ($cgi) = new CGI;  
        >         my (@dat) = $cgi->param();  
        >         foreach(@dat) {  
        >         print "Z: ".$_."<br>";  
        >         };  
        > 
        
        

        keine Anzeige.

        Ich sehe keinen Fehler.
        Deine Frage setzt einen Blick in error.txt voraus.

        am Html-Header liegts nicht,der wird vorher geprinted und alle anderen Ausgaben laufen ja.

        Du solltest mit Live-Http-Headers oder ähnlichem mal den submit Body ansehen.

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische
  2. Hallo,

    also über ein einfaches Html-Formular werden Daten übergeben.
    <input type=hidden name=foo value='bar'>
    <input type=checkbox name=auswahl value='1'>
    <input type=checkbox name=auswahl value='2'>

    Mit enctype="application/x-www-form-urlencoded" (im Default) bekommst Du bei GET auswahl=1&auswahl=2 in den QUERY_STRING. Bei einem Post liegt dasselbe in STDIN (serverseitig). Dazu kommt evntl. ein Prozent-Encoding, was hier bei den Werten 1 und 2 nicht erforderlich ist.

    Genauso sind diese Parameter dann zu parsen, damit ein Array entsteht. Am Besten Du nimmst erstmal das CGI.pm dazu, das kann auch enctype="multipart/form-data" parsen, was ein bischen komplizierter ist.

    Natürlich kannst Du auch Deinen eigenen Parser schreiben, ich selbst hab mir eine schlanke Alternative für CGI.pm geschrieben, bei Interesse kannst Du Dir das Teil mal anschauen, es funktioniert genauso wie CGI.pm nur halt kleiner und mit einem eigenen Objekt sowie einer objektunabhängigen Variante. Im Prinzip werden alle Parameter als Key auf einen Hash gelesen, wobei die Values grundsätzlich in einem Array liegen; je nach Kontext zieht dann die Funktion param() einen Einzelwert oder das ganze Array (wantarray).

    Hotti

    1. Hallo,

      Natürlich kannst Du auch Deinen eigenen Parser schreiben, ich selbst hab mir eine schlanke Alternative für CGI.pm geschrieben, bei Interesse kannst Du Dir das Teil mal anschauen, es funktioniert genauso wie CGI.pm nur halt kleiner und mit einem eigenen Objekt sowie einer objektunabhängigen Variante. Im Prinzip werden alle Parameter als Key auf einen Hash gelesen, wobei die Values grundsätzlich in einem Array liegen; je nach Kontext zieht dann die Funktion param() einen Einzelwert oder das ganze Array (wantarray).

      das wäre bestimmt eine interessante Alternative, darf ich die mal bitte sehen?

      gruß aus Senftenberg am See

      1. hi,

        das wäre bestimmt eine interessante Alternative, darf ich die mal bitte sehen?

        Na klar, Du darfst das auch gerne an Deine Bedürfnisse anpassen ;-)

          
        sub parseAll{  
            my @hq; # query  
            my @hi; # stdin  
            if( length($ENV{QUERY_STRING}) ){  
                push @hq, $ENV{QUERY_STRING};  
            }  
            # STDIN nur CONTENT_TYPE application/x-www-form-urlencoded  
            if($ENV{CONTENT_LENGTH}){  
                read(STDIN, my $pa, $ENV{CONTENT_LENGTH});  
                push @hi, $pa;  
            }  
            my $q = join('&', @hq, @hi);  
            # der eigentliche Parser  
            my %meta;  
            foreach my $pairs(split(/[&;]/, $q)){  
                my ($k, $v) = split('=', $pairs);  
                $v =~ tr/+/ /;  
                $v = uri_unescape($v);  
                $v =~ s/^\s+//;        # Leerzeichen am Anfang raus  
                $v = unpack "A*", $v;  # Leerzeichen und Newlines am Ende raus  
                push @{$meta{$k}}, $v;  
            }  
            return \%meta;  
        }  
        
        

        parseAll() wird nur einmal aufgerufen, die hashRef im return legst Du entweder auf eine globale Variable oder bindest Du an ein Objekt, hier die Objektvariante:

          
        ###########################################################################  
        # Parameter an das URL Object anfuegen  
        sub param{  
            my $self = shift; # das URL Object  
            my $key  = shift; # Schlüssel zum Parameter  
          
            # Es muss erst eine Hashreferenz erzeugt werden  
            $self->{PARAM} = parseAll() if not defined $self->{PARAM};  
          
            if($key){  
                if(not exists $self->{PARAM}{$key}){ return }  
                elsif(wantarray){ return @{$self->{PARAM}{$key}}; }  
                else{ return $self->{PARAM}{$key}->[0]; }  
            }  
            else{  
                return keys %{$self->{PARAM}};  
            }  
        }  
        ###########################################################################  
        
        

        $obj->param('feldname')

        liefert Dir je nach Kontext ein Array (checkboxen oder multiple select) oder einen Einzelwert (input). Für uri_unescape() muss vorher das Modu URI::Escape eingebunden werden, schau da mal rein. Der Translater für das + Zeichen ist ein Rudiment, es gibt im URI Encoding entweder das '+' für Leerzeichen oder eine %20 Codierung, je nach Browser. Der Delimiter in der Parameterliste kann entweder das '&' oder das ';' sein, siehe Code. Praktisch ist die Entfernung der Leerzeichen am Anfang und Ende, das kannst Du halten wie Du möchtest.

        Gute Nacht,
        Horst Siebenschläfer (Bilch)

        1. Keine Tests? Wieso sollte ich dies verwenden und nicht CGI::Minimal, CGI::Thin, CGI::Lite, CGI::Simple?

          1. Keine Tests? Wieso sollte ich dies verwenden und nicht CGI::Minimal, CGI::Thin, CGI::Lite, CGI::Simple?

            Mir doch egal was Du verwendest, die CGI-Module sind OK. Für mich liegt der Vorteil eines eigenen Parsers darin, dass ich nur noch _mein_ Modul

            use Basic;

            einbinden muss und damit habe ich alle Methoden und Daten, die ich zum Ausgeben dynamischer Inhalte brauche. Herzstück ist das URL-Objekt, was aus der digitalisierten Projektverwaltung heraus in Basic.pm erstellt wird, alle Attribute, die das Objekt haben muss (title, descr, lastmod, css...), liegen ebenfalls auf dem Server. Basic.pm beeinhaltet auch Fehlerseiten für fehlerhafte Eingaben, das ist bei mir alles voll integriert und der jetzige Programmeiraufwand zum Schreiben neuer CGIs ist auf ein absolutes Minimum reduziert, ich glaube kaum, dass das noch schlanker geht ;-)

            Basic.pm ist produktiv auf rolfrost.de

            Hotti

            1. Für mich liegt der Vorteil eines eigenen Parsers darin, dass ich nur noch _mein_ Modul [...] einbinden muss

              Das ist aber ein ziemlich schwaches Merkmal. Du hast deinen Code beworben, also stelle dich der Kritik.

              Ich habe nach Tests gefragt und keine Antwort dazu erhalten. Das Fehlen von Tests reicht in der Perlwelt schon als KO-Kriterium.

          2. Keine Tests?

            Hack!!! Mit einem geeigneten Useragent könntest Du sämtliche Formulareingaben auf byte-Ebene (binary, raw) serialisiert posten (geht nur bei POST) und brauchst dann serverseitig keinen Parser sondern liest die Daten byteweise aus STDIN in den Arbeitsspeicher. Fiktive Bezeichnung, ich nenns mal

            enctype="application/x-binary-raw-serialized" method="POST"

            und selbstverständlich habe ich das mehr als getestet: in meinem Content-Management übertrage ich auf diese Art und Weise Dateien als Objekte zum Server. Das funktioniert einwandfrei und wenn Du Dir die üblichen Datenaustausch(Transfer)formate anschaust wirst Du vieleicht auch irgendwann auf den verführerischen Gedanken kommen, dass es für MIME, base64, XML, form-data und wie die Pfosten alle heißen mögen, immer noch zweckmäßigere Alternativen gibt, die bei dem Einen oder Anderen möglicherweise noch in der Schublade schlummern weil es die Browser einfach nicht hergeben.

            Schönes Wochenende ;-)
            Horst Sonnenschein