문제

이전에 경험하지 못한 가변 범위 문제에 직면했습니다.나는 Perl의 CGI 모듈과 DBI의 do() 메소드 호출을 사용하고 있습니다.다음은 약간 단순화된 코드 구조입니다.

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

#1 자리 표시자 변수는 초기화되지 않은 것처럼 평가됩니다.다른 두 개의 자리 표시자 변수가 작동합니다.

질문:%in 해시를 큰따옴표(#2 자리 표시자)로 묶거나 값을 새 변수(#3 자리 표시자)에 다시 할당하지 않는 한 do() 컨텍스트 내에서 사용할 수 없는 이유는 무엇입니까?

나는 이것이 CGI 모듈의 ReadParse() 함수가 %in 해시에 범위를 할당하는 방법과 관련이 있다고 생각합니다. 그러나 %in이 최상위 수준에서는 사용할 수 있지만 내 작업에서는 사용할 수 없는 이유를 이해할 만큼 Perl 범위 지정을 잘 모릅니다. () 성명.

누군가가 범위 지정 문제를 이해한다면 이를 처리할 수 있는 더 좋은 방법이 있습니까?모든 %in 참조를 큰따옴표로 묶는 것은 약간 지저분해 보입니다.각 쿼리 매개변수에 대해 새 변수를 만드는 것은 현실적이지 않습니다.

분명히 말하자면, 내 질문은 변수 범위 지정 문제에 관한 것입니다.ReadParse()는 CGI로 쿼리 매개변수를 가져오는 데 권장되는 방법이 아니라는 것을 알고 있습니다.

저는 Perl 5.8.8, CGI 3.20, DBI 1.52를 사용하고 있습니다.이 글을 읽으시는 분들께 미리 감사드립니다.

@Pi & @Bob, 제안해 주셔서 감사합니다.%in의 범위를 미리 선언하는 것은 효과가 없습니다(그리고 저는 항상 strict를 사용합니다).결과는 이전과 동일합니다.db에서 col1은 null이고 cols 2 & 3은 예상 값으로 설정됩니다.

참고로 ReadParse 함수는 다음과 같습니다(아래 참조).CGI.pm의 일부인 표준 기능입니다.내가 이해하는 바에 따르면, 범위 설정 목적으로 %in 해시(엄격한 조건 충족 제외)를 초기화하려는 의도는 아닙니다. 함수가 이를 처리하는 것으로 보이기 때문입니다.

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

내 질문은 do()의 컨텍스트 내에서 %in 해시를 얻는 가장 좋은 방법이 무엇인가 하는 것 같아요.다시 한 번 감사드립니다!이것이 원래 질문에 추가 정보를 제공하는 올바른 방법이기를 바랍니다.

@단:&ReadParse 구문에 관해 들었습니다.나는 일반적으로 CGI::ReadParse()를 사용했지만 이 경우에는 방법을 고수하는 것이 가장 좋다고 생각했습니다. CGI.pm 문서에 있습니다 정확히.

도움이 되었습니까?

해결책

DBI 문서에 따르면:현재는 묶인 변수 바인딩이 작동하지 않습니다.

DBI는 내부적으로는 매우 복잡하며 불행히도 문제를 일으키는 효율성을 높이기 위해 몇 가지 회전을 거칩니다.나는 추악하고 오래된 cgi-lib 스타일 코드를 제거하라는 다른 모든 사람들의 의견에 동의합니다.지난 10년 동안 쓸모없게 된 것은 고사하고 좋은 프레임워크(go Catalyst) 없이 CGI를 수행하는 것은 충분히 불쾌합니다.

다른 팁

실제로 문서에 설명된 대로 사용하고 있는 것 같지 않습니다.https://metacpan.org/pod/CGI#COMPATIBILITY-WITH-CGI-LIB.PL

반드시 사용해야 한다면 CGI::ReadParse();더 합리적이고 덜 거친 구문인 것 같습니다.이 상황에서 큰 차이가 있다고 볼 수는 없지만 묶여 있는 변수이므로 그것이 무엇을 하는지 누가 알겠습니까 ;)

더 일반적인 $cgi->param('foo') 구문을 사용할 수 없는 특별한 이유가 있습니까?이는 조금 더 깔끔하며 훨씬 더 예측 가능한 방식으로 네임스페이스를 더럽힙니다.

use strict;.언제나.

선언해 보세요

our %in;

도움이 되는지 확인해보세요.실패하면, strict 더 유용한 오류가 발생할 수 있습니다.

무엇이 문제인지는 모르겠지만, 그렇지 않은 몇 가지 사항은 말씀드릴 수 있습니다.

  • 범위 문제가 아닙니다.그렇다면 $in{test} 작동 할 것이다.
  • 고전은 아니지 & 호출 구문.("올바른" 것은 아니지만 이 경우에는 무해합니다.)

ReadParse 불쾌한 코드입니다.호출 패키지에 전역 변수 %in을 생성하기 위해 기호 테이블을 제거합니다.더 나쁜 점은 묶인 변수이므로 이에 액세스하면 (이론적으로) 무엇이든 할 수 있다는 것입니다.CGI.pm의 소스 코드를 보면, FETCH 메소드는 단지 params() 데이터를 얻는 방법.왜 가져오는지 모르겠습니다. $dbh->do() 작동하지 않습니다.

첫째, 그것은 do의 맥락/범위에 속하지 않습니다.여전히 메인이나 글로벌의 맥락에 있습니다.Perl의 서브루틴이나 다른 '클래스'와 관련된 어떤 방식으로든 {}를 입력할 때까지 컨텍스트를 떠나지 마십시오.() 괄호 내에서는 범위를 벗어나지 않습니다.

귀하가 제공한 샘플은 초기화되지 않은 해시이며 Pi가 제안한 대로 strict를 사용하면 이러한 일이 발생하지 않게 됩니다.

귀하의 코드에 대한 보다 대표적인 예를 들어주실 수 있습니까?%IN을 어디에 어떻게 설정합니까?

거기 뭔가 아주 망가졌어.Perl의 범위 지정은 상대적으로 간단하며, 멍청한 일을 하지 않는 한 그런 이상한 것을 우연히 발견할 가능성은 거의 없습니다.제안된 대로 strict pragma(경고도 포함)를 켜세요.사실 어쨌든 둘 다 사용해야 합니다.)

%in이 어떻게 정의되어 있는지 보지 않고서는 무슨 일이 일어나고 있는지 말하기가 꽤 어렵습니다. (이게 보기 흉해 보이는 ReadParse 호출과 관련이 있는 걸까요?왜 그것을 &, btw로 시작하는 걸까요?해당 구문은 죽은 것으로 간주되어 오랫동안 사라졌습니다.)무슨 일이 일어나고 있는지 확인할 수 있도록 좀 더 많은 코드를 게시하는 것이 좋습니다.

어떤 버전의 DBI를 사용하고 있나요?을 살펴보면 DBI 변경 로그 1.00 이전 버전은 속성 인수를 지원하지 않는 것으로 보입니다.나는 "초기화되지 않은"것으로 의심됩니다. $in{test} 실제로는 undef 당신이 지나가는 곳 $dbh->do().

당신이 준 예에서 이것은 ~ 아니다 범위 지정 문제가 있거나 어떤 매개변수도 작동하지 않습니다.

DBI(또는 바인드 매개변수가 사용되는 위치가 확실하지 않은 DBD)가 타이 매직을 준수하지 않는 것 같습니다.해결 방법은 두 번째 및 세 번째 매개변수처럼 전달한 내용을 문자열화하거나 복사하는 것입니다.

SQLite와 DBI 1.53을 사용한 간단한 테스트에서는 제대로 작동하는 것으로 나타났습니다.

$ 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

사용 중인 데이터베이스를 공유하고 싶으십니까?

좋습니다. 다음을 시도해 보세요.

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

선언한 변수를 실제로 사용하므로 도움이 될 수 있으므로 범위를 제어할 수 있습니다. use strict 물을 흐릿하게 만들 수 있는 다른 불쾌한 요소 없이)

이것이 다음과 같이 보이기 시작하면서 tie() 문제가 있는 경우 다음 실험을 시도해 보세요.이것을 foo.pl로 저장하고 다음과 같이 실행하십시오. perl foo.pl "x=1"

use CGI;

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

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

인쇄해야합니다 1 1.그렇지 않다면 범인을 찾은 것입니다.

방금 테스트 코드를 사용해 보았습니다. http://www.carcomplaints.com/test/test.pl.txt, 내 컴퓨터에서는 문제 없이 바로 작동합니다.예상대로 세 가지 값을 얻습니다.CGI로 실행하지 않았지만 다음을 사용했습니다.

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

콘솔에 변수를 작성합니다(test=test) 스크립트가 문제 없이 삽입됩니다.

그러나 이것을 그대로 두면 tt는 빈 문자열과 두 개의 NULL을 삽입합니다.이는 문자열에 값을 삽입하기 때문입니다.그러면 다음 값의 문자열이 만들어집니다. $in{test} 이는 undef 지금은. undef 데이터베이스에 삽입되는 빈 문자열로 문자열화됩니다.

이 시도

%in = ReadParse();

하지만 나는 그것이 의심스럽다.쿼리 매개변수 등을 얻으려고 하시나요?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top