Question

J'ai rencontré ce qui semble être un problème de portée variable que je n'avais jamais rencontré auparavant. J'utilise le module CGI de Perl et un appel à la méthode do () de DBI. Voici la structure de code, un peu simplifiée:

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);

La variable de substitution n ° 1 est évaluée comme si elle n'était pas initialisée. Les deux autres variables d'espace réservé fonctionnent.

La question: Pourquoi le% de hachage n'est-il pas disponible dans le contexte de do (), à moins que je l'enveloppe entre guillemets (emplacement n ° 2) ou que je réaffecte la valeur à une nouvelle variable (emplacement n ° 3) ?

Je pense que cela a quelque chose à voir avec la façon dont la fonction ReadParse () du module CGI assigne la portée au% de hachage, mais je ne connais pas assez la portée de Perl pour comprendre pourquoi% in est disponible au plus haut niveau mais pas à partir de dans ma déclaration do ().

Si quelqu'un comprend le problème de portée, existe-t-il une meilleure façon de le gérer? Le fait de mettre les guillemets doubles dans les références entre guillemets semble un peu compliqué. La création de nouvelles variables pour chaque paramètre de requête n’est pas réaliste.

Pour préciser, ma question concerne le problème de la portée variable. Je réalise que ReadParse () n’est pas la méthode recommandée pour récupérer des paramètres de requête avec CGI.

J'utilise Perl 5.8.8, CGI 3.20 et DBI 1.52. Merci d’avance à tous ceux qui liront ceci.

@Pi & amp; @Bob, merci pour les suggestions. La déclaration préalable de la portée de% in n'a aucun effet (et j'utilise toujours strict). Le résultat est le même que précédemment: dans la base de données, col1 est null alors que cols 2 & amp; 3 sont définis sur la valeur attendue.

Pour référence, voici la fonction ReadParse (voir ci-dessous). C'est une fonction standard qui fait partie de CGI.pm. Si je comprends bien, je ne suis pas censé initialiser le% en hachage (autre que la satisfaction stricte) à des fins de définition de la portée, car la fonction me semble gérer cela:

sub ReadParse {
    local(*in);
    if (@_) {
      *in = 

J'ai rencontré ce qui semble être un problème de portée variable que je n'avais jamais rencontré auparavant. J'utilise le module CGI de Perl et un appel à la méthode do () de DBI. Voici la structure de code, un peu simplifiée:

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);

La variable de substitution n ° 1 est évaluée comme si elle n'était pas initialisée. Les deux autres variables d'espace réservé fonctionnent.

La question: Pourquoi le% de hachage n'est-il pas disponible dans le contexte de do (), à moins que je l'enveloppe entre guillemets (emplacement n ° 2) ou que je réaffecte la valeur à une nouvelle variable (emplacement n ° 3) ?

Je pense que cela a quelque chose à voir avec la façon dont la fonction ReadParse () du module CGI assigne la portée au% de hachage, mais je ne connais pas assez la portée de Perl pour comprendre pourquoi% in est disponible au plus haut niveau mais pas à partir de dans ma déclaration do ().

Si quelqu'un comprend le problème de portée, existe-t-il une meilleure façon de le gérer? Le fait de mettre les guillemets doubles dans les références entre guillemets semble un peu compliqué. La création de nouvelles variables pour chaque paramètre de requête n’est pas réaliste.

Pour préciser, ma question concerne le problème de la portée variable. Je réalise que ReadParse () n’est pas la méthode recommandée pour récupérer des paramètres de requête avec CGI.

J'utilise Perl 5.8.8, CGI 3.20 et DBI 1.52. Merci d’avance à tous ceux qui liront ceci.

@Pi & amp; @Bob, merci pour les suggestions. La déclaration préalable de la portée de% in n'a aucun effet (et j'utilise toujours strict). Le résultat est le même que précédemment: dans la base de données, col1 est null alors que cols 2 & amp; 3 sont définis sur la valeur attendue.

Pour référence, voici la fonction ReadParse (voir ci-dessous). C'est une fonction standard qui fait partie de CGI.pm. Si je comprends bien, je ne suis pas censé initialiser le% en hachage (autre que la satisfaction stricte) à des fins de définition de la portée, car la fonction me semble gérer cela:

<*>

Je suppose que ma question est quel est le meilleur moyen d’obtenir le% en hachage dans le contexte de do ()? Merci encore! J'espère que c'est le bon moyen de fournir des informations supplémentaires à ma question initiale.

@Dan: Je vous ai entendu parler de la syntaxe & amp; ReadParse. J'utiliserais normalement CGI :: ReadParse () mais dans ce cas, je pensais qu'il était préférable de s'en tenir à la façon dont La documentation CGI.pm l'a exactement .

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

Je suppose que ma question est quel est le meilleur moyen d’obtenir le% en hachage dans le contexte de do ()? Merci encore! J'espère que c'est le bon moyen de fournir des informations supplémentaires à ma question initiale.

@Dan: Je vous ai entendu parler de la syntaxe & amp; ReadParse. J'utiliserais normalement CGI :: ReadParse () mais dans ce cas, je pensais qu'il était préférable de s'en tenir à la façon dont La documentation CGI.pm l'a exactement .

Était-ce utile?

La solution

Selon la documentation DBI: La liaison d'une variable liée ne fonctionne pas, actuellement.

DBI est assez compliqué sous le capot, et malheureusement, il a subi quelques girations efficaces qui causent votre problème. Je suis d'accord avec tout le monde qui dit de se débarrasser du vilain vieux code de style cgi-lib. C'est assez désagréable de faire de la CGI sans un joli cadre (go Catalyst), sans parler de quelque chose qui est obsolète depuis une décennie.

Autres conseils

Il ne semble pas que vous l'utilisiez comme décrit dans la documentation: https://metacpan.org/pod/CGI#COMPATIBILITY-WITH- CGI-LIB.PL

Si vous devez l’utiliser, alors CGI :: ReadParse (); semble la syntaxe plus sensible et moins cruelle. Bien que je ne puisse pas voir que cela fait beaucoup de différence dans cette situation, mais alors c'est une variable liée, alors qui sait ce qu'il fait;)

Y a-t-il une raison particulière pour laquelle vous ne pouvez pas utiliser la syntaxe plus commune $ cg- > param ('foo')? C'est un peu plus propre, et filtre votre espace de noms de manière beaucoup plus prévisible.

utilise strict; . Toujours.

Essayez de déclarer

our %in;

et voir si cela aide. A défaut, strict peut produire une erreur plus utile.

Je ne sais pas ce qui ne va pas, mais je peux vous dire certaines choses qui ne le sont pas:

  • Ce n'est pas une question de portée. Si c'était le cas, aucune des instances de $ in {test} ne fonctionnerait.
  • Ce n'est pas la syntaxe d'appel & amp; archaïque. (Ce n'est pas "correct" mais c'est sans danger dans ce cas.)

ReadParse est un mauvais morceau de code. Il utilise la table des symboles pour créer la variable globale% in dans le package appelant. Le pire est que c'est une variable liée, donc y accéder peut (théoriquement) faire n'importe quoi. En regardant le code source de CGI.pm, la méthode FETCH appelle simplement la méthode params () pour obtenir les données. Je ne sais pas pourquoi la récupération dans $ dbh- > do () ne fonctionne pas.

Tout d’abord, ce n’est pas dans le contexte / la portée de do. C'est toujours dans le contexte de main ou global. Vous ne quittez pas le contexte tant que vous n'avez pas entré {} d'une manière ou d'une autre concernant des sous-routines ou différentes 'classes' en Perl. Dans () entre parenthèses, vous ne quittez pas la portée.

L'échantillon que vous nous avez fourni est un hachage non initialisé et, comme l'a suggéré Pi, utiliser strict empêchera certainement ceux-ci de se produire.

Pouvez-vous nous donner un exemple plus représentatif de votre code? Où mettez-vous% IN et comment?

Quelque chose est très cassé là-bas. La portée de Perl est relativement simple et il est peu probable que vous tombiez sur une chose aussi étrange que celle-là à moins que vous ne fassiez quelque chose de stupide. Comme cela a été suggéré, activez le pragma strict (et les avertissements également. En fait, vous devriez utiliser les deux de toute façon).

Il est assez difficile de dire ce qui se passe sans pouvoir voir comment% in est défini (est-ce que cela a quelque chose à voir avec cet appel ReadParse au look désagréable? Pourquoi appelez-vous cela avec la syntaxe principale? a été considéré comme mort et parti depuis longtemps). Je suggère de poster un peu plus de code, afin que nous puissions voir ce qui se passe ..

Quelle version de DBI utilisez-vous? En regardant dans le journal des modifications DBI , il semble que les versions antérieures à 1.00 ne ' t ne supporte pas l’argument attribut. Je soupçonne que le message "non initialisé" $ in {test} est en fait le undef que vous transmettez à $ dbh- > do () .

D'après l'exemple que vous avez donné, il s'agit pas d'un problème de portée, ou aucun des paramètres ne fonctionnerait.

On dirait que DBI (ou un DBD, ne sachant pas où les paramètres de liaison sont utilisés) ne respecte pas la magie de la cravate. La solution de contournement serait d’enchaîner ou de copier ce que vous lui transmettez, comme le font vos deuxième et troisième paramètres.

Un simple test utilisant SQLite et DBI 1.53 montre que tout fonctionne correctement:

$ 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

Voulez-vous partager la base de données que vous utilisez?

OK, essayez ceci:

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

Cela pourrait aider, car il utilise en fait une variable que vous avez déclarée, et peut donc contrôler la portée de (cela vous permettra en outre d'utiliser strict sans autre méchanceté qui pourrait brouiller les cartes )

Comme cela commence à ressembler à un problème tie () , essayez l'expérience suivante. Enregistrez ceci sous foo.pl et exécutez-le sous perl foo.pl "x = 1"

.
use CGI;

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

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

Il devrait imprimer 1 1 . Si ce n'est pas le cas, nous avons trouvé le coupable.

Je viens d'essayer votre code de test depuis http://www.carcomplaints.com/ test / test.pl.txt , et cela fonctionne immédiatement sur mon ordinateur, aucun problème. Je reçois trois valeurs comme prévu. Je ne l'ai pas exécuté en tant que CGI, mais en utilisant:

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

J'écris une variable sur la console ( test = test ) et vos scripts sont insérés sans problème.

Si toutefois vous laissez ceci en dehors, tt insérera une chaîne vide et deux NULL. C'est parce que vous interpolez une valeur dans une chaîne. Cela créera une chaîne avec la valeur $ dans {test} qui est undef pour le moment. undef se transforme en une chaîne vide, qui correspond à ce qui est inséré dans la base de données.

Essayez ceci

% in = ReadParse ();

mais j'en doute. Voulez-vous obtenir des paramètres de requête ou quelque chose de ce genre?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top