Pergunta

Eu tenho que correr para o que parece ser uma questão de escopo de variáveis ??que eu não encontrei antes. Eu estou usando o módulo CGI de Perl e uma chamada para o método de DBI do (). Aqui está a estrutura do código, simplificada um pouco:

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

Os avalia # 1 variáveis ??espaço reservado como se estivesse não inicializado. As outras duas variáveis ??de espaço reservado de trabalho.

A questão: Porque é que o% em hash não disponível dentro do contexto de tarefas (), a menos que eu envolvê-la entre aspas duplas (# 2 espaço reservado) ou transferir o valor para uma nova variável (# 3 espaço reservado) ?

Eu acho que é algo a ver com a forma como ReadParse do módulo CGI () designa a função escopo para o% em hash, mas eu não sei Perl escopo bem o suficiente para entender o porquê% em está disponível no nível superior, mas não de dentro do meu do () declaração.

Se alguém não entende a questão de definição do âmbito, há uma maneira melhor de lidar com isso? Envolvendo toda a% em referências em aspas parece um pouco confuso. Criando novas variáveis ??para cada parâmetro de consulta não é realista.

Só para ficar claro, a minha pergunta é sobre a questão variável de escopo. Eu percebo que ReadParse () não é o método recomendado para parâmetros de consulta agarrar com CGI.

Eu estou usando Perl 5.8.8, CGI 3,20, e DBI 1.52. Agradecemos antecipadamente a qualquer um lendo isto.

@Pi & @Bob, obrigado pelas sugestões. Pré-declarar o âmbito da% no tem nenhum efeito (e sempre uso rigoroso). O resultado é o mesmo de antes:. No db, col1 é nulo, enquanto cols 2 e 3 estão definidas para o valor esperado

Para referência, aqui está a função ReadParse (veja abaixo). É uma função padrão que faz parte do CGI.pm. A maneira que eu entendo, eu não estou destinado a inicializar o% em hash de (excepto satisfazendo estrito) para fins de âmbito definição, uma vez que as aparece função para me para lidar com isso:

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

Eu acho que a minha pergunta é qual é a melhor maneira de obter o% em hash de dentro do contexto do ()? Obrigado novamente! Espero que este é o caminho certo para fornecer informações adicionais para a minha pergunta original.

@ Dan: Eu ouço ya sobre o & sintaxe ReadParse. Eu normalmente usam CGI :: ReadParse (), mas neste caso eu pensei que era melhor manter a como a documentação CGI.pm tem exatamente.

Foi útil?

Solução

Por documentação DBI:. Encadernação uma variável vinculada não trabalha, atualmente

DBI é muito complicado sob o capô, e, infelizmente, passa por algumas oscilações para ser eficiente que estão causando o problema. Concordo com todos os outros que diz para se livrar do código de estilo cgi-lib feia e velha. É o suficiente desagradável para fazer CGI sem um quadro agradável (ir Catalisador), muito menos algo que tem sido obsoleto por uma década.

Outras dicas

Não, na verdade, parece que você está usando-o como descrito na documentação: https://metacpan.org/pod/CGI#COMPATIBILITY-WITH- CGI-LIB.PL

Se você deve usá-lo, em seguida, CGI :: ReadParse (); Parece sintaxe mais sensata e menos intrincada. Embora eu não possa vê-lo fazendo muita diferença nessa situação, mas então é uma variável vinculada, então quem diabos sabe o que está fazendo;)

Existe uma razão especial que você não pode usar o cgi> param ( 'foo') sintaxe $ mais-comum? É um pouco mais limpa, e filths até o seu namespace de uma forma consideravelmente mais previsível ..

use strict;. Sempre.

Tente declarando

our %in;

e ver se isso ajuda. Falhando isso, strict pode produzir um erro mais útil.

Eu não sei o que está errado, mas posso dizer-lhe algumas coisas que não são:

  • Não é uma questão de escopo. Se fosse, então nenhum dos casos de $in{test} iria funcionar.
  • Não é a sintaxe & chamada arcaico. (Não é "certo", mas é inofensivo neste caso.)

ReadParse é um pouco desagradável de código. Ele munges tabela de símbolos para criar a variável% global em no pacote chamado. O que é pior é que é uma variável vinculada, então acessá-lo poderia (teoricamente) fazer qualquer coisa. Olhando para o código-fonte para CGI.pm, o método FETCH apenas invoca o método params() para obter os dados. Eu não tenho idéia por que o esforço no $dbh->do() não está funcionando.

Em primeiro lugar, que não é no contexto / âmbito de afazeres. É ainda no contexto do principal ou global. Você não deixa em contexto até que você insira {} de alguma forma relacionada com sub-rotinas ou diferentes 'classes' em perl. Within () parens você não está deixando margem.

O exemplo que você nos deu é de um hash não inicializado e como Pi sugeriu, usando estrita certamente manter aqueles ocorram.

Você pode nos dar um exemplo mais representativo do seu código? Onde você está definindo% IN e como?

Algo está muito quebrado lá. escopo do Perl é relativamente simples, e é improvável que você tropeçar em cima de qualquer coisa estranha, como que a menos que você está fazendo algo idiota. Como tem sido sugerido, ligue o pragma rigorosa (e advertências, também. Na verdade, você deve estar usando tanto de qualquer maneira).

É muito difícil dizer o que está acontecendo sem ser capaz de ver como% em está definido (que é algo a ver com essa chamada ReadParse de aparência desagradável? Por que você está chamando-o com o líder e, btw? Que a sintaxe tem sido considerado morto e enterrado por um longo tempo). Sugiro postar um código mais pouco, para que possamos ver o que está acontecendo ..

Qual versão do DBI você está usando? De olhar para o DBI changelog parece que versões anteriores à 1.00 didn' t apoiar o argumento de atributo. Eu suspeito que o "não inicializado" $in{test} é realmente o undef que você está passando para $dbh->do().

A partir do exemplo que você deu, este é não uma questão de escopo, ou nenhum dos parâmetros iria funcionar.

Looks como DBI (ou uma DBD, não tenho certeza onde os parâmetros de ligação estão usado) não está honrando magia empate. A solução seria stringize ou copiar o que você passar para ele, como o seu segundo e terceiro parâmetros fazer.

Um teste simples usando SQLite e DBI 1.53 mostra que ok trabalho:

$ 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

Cuidados para compartilhar o banco de dados que você está usando?

Ok, tente o seguinte:

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

que podem ajudar, como é, na verdade, usando uma variável que você já declarou, e, portanto, pode controlar o escopo de (mais ele vai deixá-lo use strict sem outra maldade que poderia ser turvando as águas)

Como isso está começando a parecer um problema tie(), tente o seguinte experimento. Salvar isso como um foo.pl e executá-lo como perl foo.pl "x=1"

use CGI;

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

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

Deve imprimir 1 1. Se isso não acontecer, nós encontramos o culpado.

Eu apenas tentei seu codce teste de http://www.carcomplaints.com/ test / test.pl.txt , e funciona de imediato no meu computador, sem problemas. Recebo três valores como esperado. Eu não executá-lo como CGI, mas usando:

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

Eu escrevo uma variável no console (test=test) e seus scripts inserções sem nenhum problema.

Se, contudo, a sua licença isto, tt irá inserir uma cadeia vazia e dois nulos. Esta é uma porque você interpolar um valor em uma string. Esta vontade faz uma string com valor de $in{test} que é undef no momento. stringifies undef para uma cadeia vazia, que é o que é inserido no banco de dados.

Tente este

=% em ReadParse ();

mas eu duvido disso. Você está tentando obter parâmetros de consulta ou algo assim?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top