Frage

Ich habe laufen in, was scheint, eine Variable Umfang Frage, die ich vorher noch nicht begegnet ist. Ich bin mit dem Perl-CGI-Modul und einen Aufruf an DBI do () -Methode. Hier ist der Code-Struktur, vereinfacht ein bisschen:

use DBI;
use CGI qw(:cgi-lib);
&ReadParse;
my $dbh = DBI->connect(...............);
my $test = $in{test};
$dbh->do(qq{INSERT INTO events VALUES (?,?,?)},undef,$in{test},"$in{test}",$test);

Die # 1 Platzhalter Variable auswertet, als ob es nicht initialisiert ist. Die anderen beiden Platzhalter Variablen arbeiten.

Die Frage: Warum im Rahmen von do () die% in Hash nicht verfügbar ist, wenn ich es in doppelte Anführungszeichen wickeln (# 2 Platzhalter) oder den Wert in eine neue Variable (# 3 Platzhalter) zuweisen ?

Ich denke, es ist etwas mit, wie der CGI-Moduls ReadParse () Funktion ordnet Umfang in das Verzeichnis% in Hash zu tun, aber ich weiß nicht, Perl Scoping gut genug, um zu verstehen, warum% in auf der obersten Ebene vorhanden ist, aber nicht von in meiner do () Erklärung.

Wenn jemand das Scoping-Problem nicht verstehen, gibt es einen besseren Weg, um es zu behandeln? Wrapping all% in Referenzen in doppelten Anführungszeichen scheint ein wenig chaotisch. Erstellen von neuen Variablen für jeden Abfrage-Parameter ist nicht realistisch.

Just klar zu sein, meine Frage bezieht sich auf die Variable Scoping Problem. Ich weiß, dass ReadParse () ist nicht die empfohlene Methode Abfrage params mit CGI zu greifen.

Ich bin mit Perl 5.8.8, CGI 3.20 und DBI 1,52. Vielen Dank im Voraus für jeden der Lektüre dieses.

@Pi & @Bob, vielen Dank für die Anregungen. für% den Umfang Pre-Deklaration hat in keine Wirkung (und ich verwende immer streng). Das Ergebnis ist das gleiche wie zuvor. In der db, col1 null ist, während cols 2 & 3 auf den erwarteten Wert gesetzt werden

Als Referenz hier ist die ReadParse Funktion (siehe unten). Es ist eine Standardfunktion, die Teil CGI.pm. ist So wie ich es verstehe, ich bin das% in Hash (andere als erfüllt strengen) zum Zweck der Einstellung Umfangs zu initialisieren nicht dazu gedacht, da die Funktion mir scheint, dass zu behandeln:

sub ReadParse {
    local(*in);
    if (@_) {
      *in = $_[0];
    } else {
    my $pkg = caller();
      *in=*{"${pkg}::in"};
    }
    tie(%in,CGI);
    return scalar(keys %in);
}

Ich denke, meine Frage ist, was der beste Weg ist, um das% im Hash im Rahmen von do () zu bekommen? Danke noch einmal! Ich hoffe, dass dies der richtige Weg ist, zusätzliche Informationen zu meiner ursprünglichen Frage zu geben.

@ Dan: Ich höre ya in Bezug auf die & ReadParse Syntax. Ich würde normalerweise CGI verwenden :: ReadParse (), aber in diesem Fall fand ich es am besten zu bleiben, wie die CGI.pm Dokumentation hat es genau.

War es hilfreich?

Lösung

Per DBI Dokumentation. Die Bindung eines gebundenen Variable funktioniert nicht, zur Zeit

DBI ist ziemlich unter der Haube kompliziert, und leider geht durch einige Verrenkungen effizient zu sein, dass Ihr Problem verursachen. Ich stimme mit allen anderen, der sagt, der hässliche alte cgi-lib Artcode loszuwerden. Es ist unangenehm genug CGI zu tun, ohne einen schönen Rahmen (go Katalysator), geschweige denn etwas, das seit einem Jahrzehnt veraltet gewesen ist.

Andere Tipps

Es ist nicht wirklich so aussehen wie Sie es verwenden, wie in der Dokumentation beschrieben: https://metacpan.org/pod/CGI#COMPATIBILITY-WITH- CGI-LIB.PL

Wenn Sie es verwenden müssen, dann CGI :: ReadParse (); scheint sinnvoller und weniger crufty Syntax. Obwohl ich kann es nicht sehen in dieser Situation machen viel Unterschied, aber dann ist es eine gebundene Variable, also wer zum Teufel weiß, was er tut;)

Gibt es einen bestimmten Grund, warum Sie nicht den mehr-common $ cgi- verwenden> param ( 'foo') Syntax? Es ist ein wenig sauberer und filths Ihren Namensraum in einem deutlich vorhersehbarer Weise auf ..

use strict;. Immer.

Versuchen Sie erklären

our %in;

und zu sehen, ob das hilft. Gelingt das nicht, strict kann einen nützlichen Fehler.

Ich weiß nicht, was los ist, aber ich kann Ihnen einige Dinge sagen, die nicht sind:

  • Es ist kein Scoping Problem. Wenn es dann keiner der Fälle von $in{test} funktionieren würde.
  • Es ist nicht die archaische & Aufrufsyntax. (Es ist nicht „richtig“, aber es ist harmlos in diesem Fall).

ReadParse ist ein böses Stück Code. Es munges die Symboltabelle das globale Variable% in dem anrufenden Paket zu erstellen. Noch schlimmer ist, dass es sich um eine Variable gebunden ist, so Zugriff auf es könnte (theoretisch) nichts zu tun. Mit Blick auf den Quellcode für CGI.pm ruft die FETCH Methode nur die params() Methode die Daten zu erhalten. Ich habe keine Ahnung, warum in der $dbh->do() den Abruf nicht funktioniert.

Zum einen das ist nicht im Kontext / Umfang do. Es ist nach wie vor im Rahmen der Haupt- oder global. Sie müssen nicht Kontext lassen, bis Sie {} in irgendeiner Weise im Zusammenhang mit Subroutinen oder verschiedene ‚Klassen‘ in Perl ein. Innerhalb () parens Sie sind nicht Umfang zu verlassen.

Die Probe Sie gaben uns von einem nicht initialisierten Hash ist und wie Pi vorgeschlagen hat, wird mit strengen sicherlich diejenigen, die aus auftretenden zu halten.

Können Sie uns ein repräsentatives Beispiel des Codes? Wo setzen Sie% IN und wie?

Etwas dort sehr gebrochen. Perl Scoping ist relativ einfach, und Sie sind wahrscheinlich nicht auf irgendetwas stolpern seltsam wie, dass, wenn Sie etwas bescheuert tun. Wie vorgeschlagen, schalten Sie die strengen Pragma (und Warnungen, auch. In der Tat sollten Sie verwenden beide sowieso).

Es ist ziemlich schwer zu sagen, was ohne in der Lage ist los zu sein, um zu sehen, wie% in definiert ist (ist es etwas damit zu tun, böse aussehende ReadParse nennen? Warum rufen Sie es mit dem führenden &, btw? Dass Syntax in Betracht gezogen worden für eine lange Zeit tot und gegangen). Ich schlage vor, ein bisschen mehr Code veröffentlichen, damit wir sehen können, was los ist ..

Welche Version von DBI verwenden Sie? Vom Blick auf dem DBI Changelog scheint es, dass Versionen vor 1.00 didn‘ t unterstützen das Attribut Argument. Ich vermute, dass die „nicht initialisierte“ $in{test} ist eigentlich die undef, dass Sie zu $dbh->do() vorbei.

Aus dem Beispiel ihr habt, das ist nicht ein Scoping-Ausgabe, oder keiner der Parameter funktionieren würde.

Sieht aus wie DBI (oder einem DBD, nicht sicher, wo bind Parameter verwendet werden) ehrt nicht Krawatte Magie. Die Abhilfe wäre stringize oder zu kopieren, was Sie es passieren, wie Ihre zweite und dritte Parameter tun.

Ein einfacher Test mit SQLite und DBI 1.53 zeigt es funktioniert ok:

$ perl -MDBI -we'sub TIEHASH { bless {} } sub FETCH { "42" } tie %x, "main" or die; my $dbh = DBI->connect("dbi:SQLite:dbname=dbfile","",""); $dbh->do("create table foo (bar char(80))"); $dbh->do("insert into foo values (?)", undef, $x{foo}); print "got: " . $dbh->selectrow_array("select bar from foo") . "\n"; $dbh->do("drop table foo")'
got: 42

Pflege zu teilen, welche Datenbank Sie verwenden?

Okay, versuchen Sie dies:

use CGI;
my %in;
CGI::ReadParse(\%in);

Das könnte helfen, wie es eigentlich eine Variable, die Sie deklariert haben, und damit den Umfang kontrollieren kann (plus es lasse Sie ohne andere Gemeinheit use strict, die die Gewässer werden muddying könnte)

Da es sich wie ein tie() Problem zu suchen beginnt, versuchen Sie das folgende Experiment. Speichern Sie diese als foo.pl und führen Sie es als perl foo.pl "x=1"

use CGI;

CGI::ReadParse();
p($in{x}, "$in{x}");

sub p { my @a = @_; print "@a\n" }

Es sollte 1 1 drucken. Wenn dies nicht geschieht, haben wir die Schuldigen gefunden.

Ich habe gerade versucht, den Test codce von http://www.carcomplaints.com/ Test / test.pl.txt , und es funktioniert sofort auf meinem Computer, keine Probleme. Ich erhalte drei Werte wie erwartet. Ich habe es nicht als CGI laufen, aber mit:

...
use CGI qw/-debug/;
...

Ich schreibe eine Variable auf der Konsole (test=test) und Ihre Skripte einfügt, ohne ein Problem.

Wenn jedoch Ihre leave this out, tt wird eine leere Zeichenfolge und zwei NULL-Werte einfügen. Dies ist ein, weil Sie einen Wert in einen String interpolieren. Dieser Wille macht einen String mit dem Wert von $in{test} der im Moment undef wird. undef stringifies auf einen leeren String, das ist, was in der Datenbank eingefügt wird.

Versuchen Sie, diese

% in = ReadParse ();

, aber ich bezweifle, dass. Versuchen Sie, Abfrageparameter oder etwas zu bekommen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top