2012-11-05 2 views
1

나는 못을 박을 수없는 버그로 고생하고 있습니다.템플릿 툴킷에서 변수에 액세스하는 이상한 버그

나는 우편 번호를 가지고 조회를하고 위도, 경도 및 지역 이름을 반환하는 함수를 가지고있다.

예를 들어, 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 (부분적으로) 내부에서 가져온 것입니다.

그래서 어떤 아이디어가 계속 될지, 어디에서 시작해야할까요? 이것을 더 시도하고 디버깅하려면 어떻게해야합니까? 나는 아이디어가 없어.

+0

실제로 TT의 은닉으로 끝나는 코드를 게시하지 않을 때 어떤 일이 잘못 될지 추측하기는 어렵습니다. 의미 :'$ self -> {data}'를 TT에 숨겨둔 것으로 해석하는 코드를 보여줍니다. '$ self -> {data} = $ param {data} ||를 할당하는 코드를 보여줍니다. []'(그 자체로는 물고기처럼 보입니다 : TT는 배열 ref가 아닌 hash ref를'process'의 두 번째 매개 변수로 기대합니다) 그러나'$ param {data} '이 지정되었을 수 있습니다. –

+0

나는 그것이 상당히 명백하다고 생각했다. $ param -> {data}는 hashref이고 $ param-> data는 $ hash { 'area'} = 'string value'와 같이 해시 (ref to a) 해시를 포함합니다. 더 묻고 싶은게 분명하지 않아? – mark

+0

@MoritzBunkus가 말한 것은 $ self -> {data} = $ params -> {data} || []; 문제는 $ params -> {data} (HashRef라고하는)가 undef 일 경우 빈 ArrayRef "[]"를 생성하기 때문에 문제가됩니다. 따라서 $ params -> {data}는 상황에 따라 ArrayRef 또는 HashRef가 될 수 있습니다. {}을 의미하지 않는다고 확신합니까? – oalders

답변

0

다른 개발 서버와 프로덕션 서버에서 문제가 없어졌습니다.

따라서 TT를 제거하고 다시 설치하려고했지만 도움이되지 않았습니다.

내 dev 서버에 환경 문제가있는 것처럼 보이므로 상자를 퇴역시키고 새로운 서버를 시작합니다.

0

아마도 $ 영역은 축복받은 대상이기 때문일 수 있습니다. 스칼라 문자열로 변환하려면이 시도 :

print ref($area); 
use Data::Dumper; warn Dumper($area); 

및 Q { ","} 오버로드 :

print defined ${ref($area).'::'}{'(""'}; 

@Moritz의 의견에 따라
$string = ''.$area; 
# e.g. 
$hash->{'area'} = ''.$area; 

, 즉 $ 영역이 축복 확인

EDIT

하위 릴리스는 을 반환 할 수 있습니다. $ postcode가 false로 평가되면 undef를 반환 할 수 있습니다.-이 같은 스칼라 문맥에서 사용되지만으로 목록 $ REGION_NAME 또는 $ 영역을 덤프와 관련, 아니면 from_postcode보고

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

괄호 목록처럼 마지막 인수 $의 REGION_NAME (쉼표로 표현)를 반환 .

+0

단순히 문자열에 값을 넣는 것 외에도 OP는'$ area'가 실제로 축복을 받았는지 여부를 알아낼 수도 있습니다. 'ref $ area'를 출력하거나'Use Data :: Dumper; 덤퍼에게 경고 ($ 영역);'. –

+0

답변이 업데이트되었습니다. –

+0

안녕하세요, 감사합니다. 위 경로를 따라 생각해 볼 수있는 모든 것을 시도했습니다. 나는 여러 가지 미친 것들을 절망적으로 시도했다. (새로운 해쉬를 함께 할당하는 것과 같지만 여전히 동일하다.) 나는 데이터 덤프로 질문을 편집했다 - 당신에게 잘 보이나요? – mark