Schrift
[thread]495[/thread]

CGI.pm und Arrays von Parametern



<< >> 5 Einträge, 1 Seite
Ronnie
 2005-05-24 21:19
#4964 #4964
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Wenn CGI.pm eine Liste von Werten als Parameter erhält, werden diese im Hash den man via $form = $cgi->Vars() erhält nicht als Referenz auf ein Array sondern als mit \0-Bytes getrennte Zeichenkette abgelegt. Es gibt zwei Möglichkeiten ein entsprechendes Array zu erhalten:
Code: (dl )
1
2
die Dumper [split (/\0/, $form->{'list_of_selections'})];
die Dumper [$cgi->param('auswahl')];

Beide funktionieren problemlos. Aber folgendes funktioniert unerklärlicherweise nicht:
Code: (dl )
1
2
$form->{'list_of_selections'} = [$cgi->param('list_of_selections')];
die Dumper $form;

Man bekommt als dump folgendes:
Code: (dl )
1
2
3
4
$VAR1 = {
'list_of_selections' => 'ARRAY(0x81642e0)',
'action' => 'send'
};

Wieso bekommt man das entsprechende Array von Data::Dumper nicht angezeigt?
pKai
 2005-05-24 23:58
#4965 #4965
User since
2005-02-18
357 Artikel
BenutzerIn
[default_avatar]
Vars() liefert im skalaren Kontext einen Hashref zurük, der per tie an das CGI-Objekt gebunden ist.
Das Tie ist über Aufrufe von param() implementiert.
Deine Zuweisung
Code: (dl )
1
2
$h=$cgi->Vars();
$h{'x'} = [ 1, 2 ];

wird durch die entsprechende sub STORE als
Code: (dl )
$cgi->param('x', [1, 2]);

und das Lesen (in Dumper) durch FETCH als
Code: (dl )
join("\0", $cgi->param('x'));
realisiert.
Da haben wir dann die String-Interpolation, die zu der 'ARRAY(...)'-Ausgabe führt.\n\n

<!--EDIT|pKai|1116964760-->
I sense a soul in search of answers.
Dubu
 2005-05-24 23:59
#4966 #4966
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Dein $form ist nicht einfach eine Hashreferenz, sondern eine Referenz auf einen mit tie() an das CGI-Objekt gebundenen Hash.

Wenn du Elementen aus $form etwas zuweist, rufst du damit also die STORE-Methode in CGI.pm fuer diesen Hash auf, und die sieht so aus:
Code: (dl )
1
2
3
4
5
6
7
sub STORE {
   my $self = shift;
   my $tag  = shift;
   my $vals = shift;
   my @vals = index($vals,"\0")!=-1 ? split("\0",$vals) : $vals;
   $self->param(-name=>$tag,-value=>\@vals);
}

In $self steht die Klasse (hier CGI), in $tag der Key (bei dir 'list_of_selections') und in $vals der zuzuweisende Wert. Wie man gut sehen kann, wird dabei $vals immer als Skalar interpretiert, evtl. auch als String mit eingebetteten Nullbytes fuer Mehrfachauswahlen. Somit landet statt deiner Arrayreferenz deren stringifizierte Darstellung ('ARRAY(0x81642e0)') im Hash.

Die Vorgehensweise ist in diesem Zusammenhang auch sinnvoll, denn so kann CGI.pm die Formulardaten weiter verwenden, z.B. um sie zu speichern oder als Default fuer das wieder aufgerufenen Formular zu nehmen.

Wenn du wirklich eine Kopie des Hashes haben moechtest, die du beliebig veraendern kannst, dann musst du sie anlegen, z.B. direkt beim Aufruf von Vars():
Code: (dl )
1
2
3
my %form = $cgi->Vars();
# oder als Referenz
my $form = { $cgi->Vars() };



PS: Ich wusste das mit dem tied hash bis eben auch nicht, aber nachdem ich dein Beispiel nachvollzogen hatte und es mir auch merkwuerdig vor kam, half ein Blick in die Definitionen von [tt]Vars() und [font=courier]STORE()[/tt] in CGI.pm.[/font]

Edit: pKai war schneller. 8)\n\n

<!--EDIT|Dubu|1116964853-->
Ronnie
 2005-05-25 00:03
#4967 #4967
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Danke, das ist verständlich. Wäre ich auch nicht so ohne weiteres drauf gekommen.
pKai
 2005-05-25 00:15
#4968 #4968
User since
2005-02-18
357 Artikel
BenutzerIn
[default_avatar]
Als jemand, der die CGI.pod ins Deutsche übersetzt, war ich ja fast gezwungen das nachzuvollziehen ;)
Beachte, dass erst das cgi-lib-kompatible FETCH die String-Interpolation durchführt!
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
use CGI;
use Data::Dumper;
use strict;

my $q = CGI->new;

$q->param('form', 1 .. 5);

my $h = $q->Vars();

$h->{'form'} = [ 4 .. 6 ];

print Dumper($h, $q), $/;
I sense a soul in search of answers.
<< >> 5 Einträge, 1 Seite



View all threads created 2005-05-24 21:19.