【发布时间】:2012-10-25 06:42:12
【问题描述】:
我正在与一个我无法确定的错误作斗争。
我有一个函数,它接受邮政编码、进行查找并返回纬度、经度和地区名称。
例如,将它传递给 AD300 它会返回(类似于)42.6、1.55、ordino - 它工作得很好。
函数是这样调用的:
my ($lat, $lng, $area) = $object->release();
返回值很好,我可以在 perl 中打印它们并发出警告
warn "Area $area, $rellat, $rellng";
这很好用。 "Area Ordino, 42.6, 1.55"
然后我取其中一个值,比如 $area,将其添加到数据散列中,并将其传递到通过 TT 对其进行预处理的网页(就像我成功加载其他变量一样)。
我以正常方式将值分配给哈希。例如 $hash->{'area'} = $area;
这里是乐趣的开始。当我尝试引用 TT 中的值时,例如[% hash.area %] 我没有在网页上打印“Ordino”,我被告知我已将 Array 引用传递给 TT。
经过一些调试,我发现我的哈希变量 hash.area 以某种方式引用了一个数组(根据 TT),该数组包含我从子例程“release”返回的三个值。 IE。 hash.area = [42.6, 1.55, ordino] 根据 TT。
也就是说,要在网页中获取值“Ordino”,我必须访问 [% hash.area.2 %]。
此外,我可以将 $hash->{'area'} 设置为等于任何变量 $lat、$lng 或 $area 并获得相同的行为。 TT 认为所有三个变量都引用同一个数组。那是
$lat = $lng = $area = [42.6, 1.55, ordino] 根据 TT
这很奇怪,我可以愉快地在 perl 中打印变量,它们看起来很正常——而不是数组。我试过用转储器转储哈希,没有数组,一切都很好。然而不知何故,TT 正在寻找一个数组。这让我很头疼。
这个网站很大,有很多页面,我很高兴一直通过 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 对象,并且是“新”函数的一部分(参考下文)。 “数据”包含哈希。 “输出”保存已处理的模板准备发送到用户浏览器。我们调用 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'}(请注意,数据中的 release == 区域。名称因不相关的原因而更改)。如您所见,dumper 认为它是一个字符串。 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' )
]
};
处理后出来的是这个(在$output中) 有一个 [% FOREACH 在气泡中浮出 %]
在 ARRAY(0xfaf5d448) 周围浮动。
来自 [% 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;
}
}
然后控制器获取 $bubble,将其与会话/站点数据捆绑在一起,将其放入匿名哈希中(如您在上面的数据中所见)并将其传递给视图进行处理。
发布代码为:
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::Location 很大,但是相关的行是;
$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 期望一个哈希引用,而不是一个数组引用,作为process的第二个参数),但是你没有显示函数在什么地方被调用@ 987654332@ 可能已被分配。 -
我认为这很明显。 $param->{data} 是一个 hashref,并且 $param->data 包含一个 (ref to a) hash 描述 $hash{'area'} = 'string value';我不清楚你还要求什么?
-
我认为@MoritzBunkus 所说的是 $self->{data} = $params->{data} || [];是有问题的,因为如果 $params->{data}(你说它是一个 HashRef)是 undef,你正在创建一个空的 ArrayRef“[]”。因此,根据情况,$params->{data} 可以是 ArrayRef 或 HashRef。你确定你说的不是 {}?
-
@oalders 说了什么。我还意味着显示实际构造所述哈希的代码。这意味着我想查看原始代码,在其中我可以看到从函数调用到
$object->release()到调用$self->{tt}->process()的数据流。为了使它完整,我还希望看到一些原始模板代码,而不仅仅是上面的示例。您要求我们在复杂的数据流中发现问题,因此请向我们提供该数据流中涉及的所有部分。 -
好的,明白了,还有很多事情要做,但我已经更新了数据转储(在涉及 TT 的时候)和相关代码。如果您仍然认为缺少东西,请告诉我。我不能真正从控制器中切入完整的处理循环——有很多功能,它没有意义。但是,您可以看到数据是正确的。我同意你关于 [] 的观点 - 它在这里不相关,因为数据包含数据,但我肯定会修复它。 ta.
标签: perl template-toolkit