나는 못을 박을 수없는 버그로 고생하고 있습니다.템플릿 툴킷에서 변수에 액세스하는 이상한 버그
나는 우편 번호를 가지고 조회를하고 위도, 경도 및 지역 이름을 반환하는 함수를 가지고있다.
예를 들어, AD300을 전달하면 42.6, 1.55, ordino와 같이 반환됩니다. 아주 잘 작동합니다.
my ($lat, $lng, $area) = $object->release();
반환 값은 괜찮, 나는이 잘 작동하는 경고
warn "Area $area, $rellat, $rellng";
와 펄에 인쇄 할 수 있습니다 :
기능은 다음과 같이 호출된다. "Area Ordino, 42.6, 1.55"
다음 중 하나의 값을 가져 와서 $ area를 데이터 해시에 추가하고 TT를 통해 사전 처리되는 웹 페이지로 전달합니다 (성공적으로 수행함). 다른 변수들이로드 됨).
나는 정상적인 방법으로 해시에 값을 할당하고 있습니다. 예 : $ hash -> { 'area'} = $ area;
여기 재미가 시작됩니다. TT에서 값을 참조하려고 할 때 예 : [% hash.area %] 웹 페이지에 "Ordino"가 인쇄되지 않고 TT에 대한 Array 참조를 전달했다고합니다.
약간의 디버깅 후, 해시 변수 hash.area가 어떻게 든 서브 루틴 "릴리스"에서 반환 한 세 개의 값을 보유하고있는 배열 (TT에 따라)을 참조하고 있음을 발견했습니다. 나는. TT에 따라 hash.area = [42.6, 1.55, ordino].
즉, 웹 페이지에서 "Ordino"값을 얻으려면 [% hash.area.2 %]에 액세스해야합니다.
또한, $ hash -> { 'area'}를 $ lat, $ lng 또는 $ area 변수와 동일하게 설정하여 동일한 동작을 얻을 수 있습니다. TT는 세 변수가 모두 같은 배열을 참조한다고 생각합니다. 즉
$ 위도 = $ LNG = $ 면적 = 42.6, 1.55, 디노] TT
이 bizare하다에있어서, I는 게 펄 변수를 인쇄 할 수 있으며 정상적으로 표시 금지 - 배열 . 난 덤퍼, 아니 배열로 해시를 덤핑했는데, 다 괜찮아요. 그러나 어떻게 든 TT는 배열을 찾고 있습니다.
이 사이트는 많은 페이지를 가지고 아주 크며, 나는 행복하게 변수와 해시를 웹 페이지에 전달하고 4 년 동안 해왔다. 나는 이것을 본 적이 없다. 다른 페이지에서는 "release"메서드에서 동일한 출력을 전달하기 만하면 올바르게 처리됩니다.
나는 라고 생각합니다. 내 TT 처리 코드가 문제이지만 다음은 관련이 있습니다.
my $tt = Template->new({
INCLUDE_PATH => [ @$template_directories ],
COMPILE_EXT => '.ttc',
COMPILE_DIR => '/tmp/ttc',
FILTERS => YMGN::View->filters,
PLUGIN_BASE => [ 'YMGN::V::TT::Plugins' ],
EVAL_PERL => 1
});
$self->{tt} = $tt;
$self->{template_directories} = $template_directories;
$self->{output} = $params->{output} || undef;
$self->{data} = $params->{data} || [];
위의 내용은 새 tt 개체를 만들고 "새"기능 (아래 참조)의 일부입니다. "data"는 해시를 포함합니다. "출력"은 처리 된 템플릿을 사용자 브라우저에 보낼 준비가되어 있습니다. 우리는 new (위)를 호출하고 데이터를 처리하고 아래 코드로 결과를 만듭니다.
sub process {
my $self = shift;
my $params = shift;
if (!ref $self || !exists $self->{tt}) {
my $class = $self;
$self = $class->new($params);
}
if (!$self->{output}) {
die "You need to specify output";
}
delete $self->{error};
$self->y->utils->untaint(\$self->{template});
my $rv = $self->{tt}->process(
$self->{template},
$self->{data},
$self->{output},
binmode => ':utf8',
);
if (!$rv) {
warn $self->{tt}->error();
return {
error => $self->{tt}->error(),
};
}
return 0;
}
위의 모든 것들은 계속 진행되고 있기 때문에 위생 처리되었습니다. 중요한 것은 중요한 데이터가 올바르게 보이고 있다는 것입니다. 처리중인 전체 데이터를 처리하는 tt가 전체 덤프입니다. 문제를 일으키는 것은 거품 -> [*] -> { 'release'}입니다 (데이터의 릴리스 == 영역으로, 이름은 관련이없는 이유로 변경되었습니다). 보시다시피, 덤퍼는 그것이 문자열이라고 생각합니다. TT는 그 밖의 모든 것을 잘 처리합니다. 처리 후 나오는 어떤
data $VAR1 = {
'system' => {
system stuff
},
'features' => {
site feature config
},
'message_count' => '0',
'bubbles' => [
bless({
'history' => [
{
'creator' => '73',
'points' => '10',
'screenname' => 'sarah10',
'classname' => 'Flootit::M::Bubbles',
'id' => '1378',
'updated' => '1352050471',
'type' => 'teleport',
'label' => 'teleport',
'class' => 'Flootit::M::Bubbles'
}
],
'creator' => '6',
'release' => 'Escaldes-Engordany',
'image' => 'http://six.flooting.com/files/833/7888.png',
'pop_time' => '1352050644',
'y' => $VAR1->{'y'},
'taken_by' => '0',
'city' => '3',
'title' => 'hey a new bubble',
'id' => '566',
'class' => 'Flootit::M::Bubbles',
'prize' => 'go for it kids'
}, 'Flootit::M::Bubbles'),
bless({
'history' => [
{
'creator' => '6',
'points' => '10',
'screenname' => 'sarah20',
'classname' => 'Flootit::M::Bubbles',
'id' => '1723',
'updated' => '1349548017',
'type' => 'teleport',
'label' => 'teleport',
'class' => 'Flootit::M::Bubbles'
},
{
'creator' => '6',
'points' => '5',
'screenname' => 'sarah20',
'classname' => 'Flootit::M::Bubbles',
'id' => '1732',
'updated' => '1349547952',
'type' => 'blow',
'label' => 'blow',
'class' => 'Flootit::M::Bubbles'
}
],
'creator' => '89',
'release' => 'Ordino',
'image' => 'http://six.flooting.com/files/1651/8035.png',
'pop_time' => '1351203843',
'y' => $VAR1->{'y'},
'taken_by' => '0',
'city' => '3',
'title' => 'test4',
'id' => '1780',
'class' => 'Flootit::M::Bubbles',
'prize' => 'asdfasdf dsadsasdfasdfasdf'
}, 'Flootit::M::Bubbles'),
bless({
'history' => [],
'creator' => '6',
'release' => 'Andorra la Vella',
'image' => 'http://six.flooting.com/files/1671/8042.png',
'pop_time' => '0',
'y' => $VAR1->{'y'},
'taken_by' => '0',
'city' => '3',
'title' => 'Pretty flowers, tres joli',
'id' => '1797',
'class' => 'Flootit::M::Bubbles',
'prize' => 'With lots of pretty pictures'
}, 'Flootit::M::Bubbles'),
bless({
'history' => [],
'creator' => '6',
'release' => 'Hillrise Ward',
'image' => 'http://six.flooting.com/files/1509/8003.png',
'pop_time' => '0',
'y' => $VAR1->{'y'},
'taken_by' => '0',
'city' => '3',
'title' => 'Test beats',
'id' => '1546',
'class' => 'Flootit::M::Bubbles',
'prize' => 'Sound great'
}, 'Flootit::M::Bubbles')
]
};
는이 ($ 출력에서) 어레이 (0xfaf5d448) 떠도는 [거품 % IN %의 foreach는 floot]
있다.
에서 [% floot.release %]우리가 이것을 만들면 [% floot.release.2 %] 올바른 값을 제공합니다.
다른 모든 필드는 올바르게 참조 할 수 있습니다 (그림 참조).
"거품"을 함께 묶는 코드는 다음과 같습니다.
my $bubbles = $y->model('Bubbles')->search(['type' => 'golden', 'image' => '!NULL',
'bubble_prizes' => ['p', { 'p.bubble' => 'self.id'}], ], {
order_by => '(created>CURRENT_DATE() AND thumbsup+thumbsdown<10) DESC, COALESCE(thumbsup,0)-COALESCE(thumbsdown,0) DESC, pop_time DESC',
count => 10,
fields => ['p.title as title', 'p.prize as prize', 'city', 'taken_by', 'pop_time', 'id', 'creator'],
});
for (my $i=0; $i<@$bubbles; $i++) {
# Find specified bubbles (see below for when not found here)
my ($rellat, $rellng, $area) = $bubbles->[$i]->release() ;
$bubbles->[$i]->{'release'} = $area;
}
}
제어부는, 세션/위치 데이터와 그것을 번들 $ 거품을 얻어 (위의 데이터에서 볼 수 있듯이) 익명 해시 안에 넣는다 처리보기로 전달.
릴리스에 대한 코드는 다음과 같습니다
sub release {
my $self = shift;
my $postcode = $self->y->model('Prizes')->find({bubble => $self->id})->postcode;
my ($user_lat, $user_long, $region_name);
if($postcode)
{
($user_lat, $user_long, $region_name) = $self->y->api('Location')->from_postcode($postcode);
return ($user_lat, $user_long, $region_name);
}
}
API :: 위치 그러나 관련 라인은 매우 큰;
$postcode_record = $self->y->model('GeoData')->find({
source => "ALL_COUNTRIES_POSTCODES",
country => $country_code,
sourceid => $postcode, });
return ($postcode_record->latitude, $postcode_record->longitude, $postcode_record->town);
내가 본 데이터 덤프는 TT.pm (부분적으로) 내부에서 가져온 것입니다.
그래서 어떤 아이디어가 계속 될지, 어디에서 시작해야할까요? 이것을 더 시도하고 디버깅하려면 어떻게해야합니까? 나는 아이디어가 없어.
실제로 TT의 은닉으로 끝나는 코드를 게시하지 않을 때 어떤 일이 잘못 될지 추측하기는 어렵습니다. 의미 :'$ self -> {data}'를 TT에 숨겨둔 것으로 해석하는 코드를 보여줍니다. '$ self -> {data} = $ param {data} ||를 할당하는 코드를 보여줍니다. []'(그 자체로는 물고기처럼 보입니다 : TT는 배열 ref가 아닌 hash ref를'process'의 두 번째 매개 변수로 기대합니다) 그러나'$ param {data} '이 지정되었을 수 있습니다. –
나는 그것이 상당히 명백하다고 생각했다. $ param -> {data}는 hashref이고 $ param-> data는 $ hash { 'area'} = 'string value'와 같이 해시 (ref to a) 해시를 포함합니다. 더 묻고 싶은게 분명하지 않아? – mark
@MoritzBunkus가 말한 것은 $ self -> {data} = $ params -> {data} || []; 문제는 $ params -> {data} (HashRef라고하는)가 undef 일 경우 빈 ArrayRef "[]"를 생성하기 때문에 문제가됩니다. 따라서 $ params -> {data}는 상황에 따라 ArrayRef 또는 HashRef가 될 수 있습니다. {}을 의미하지 않는다고 확신합니까? – oalders